1 /-
2 Copyright (c) 2015 Microsoft Corporation. All rights reserved.
3 Released under Apache 2.0 license as described in the file LICENSE.
4 Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
5
6 List permutations.
7 -/
8 import data.list.basic logic.relation
src └─────────────┘ └────────────┘
9
10 namespace list
11 universe variables uu vv
12 variables {α : Type uu} {β : Type vv}
13
14 /-- `perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
15 of each other. This is defined by induction using pairwise swaps. -/
16 inductive perm : list α → list α → Prop
id └──┘ └──┘
src └──┘ └──┘
typ └──┘ └──┘
17 | nil : perm [] []
id └┘ └┘
src └┘ └┘
typ └┘ └┘
18 | skip : Π (x : α) {l₁ l₂ : list α}, perm l₁ l₂ → perm (x::l₁) (x::l₂)
id └──┘ └──┘ └┘ └┘ ┴└┘└┘ ┴└┘└┘
src └──┘ └┘ └┘
typ └──┘ └──┘ └┘ └┘ ┴└┘└┘ ┴└┘└┘
19 | swap : Π (x y : α) (l : list α), perm (y::x::l) (x::y::l)
id └──┘ ┴└┘┴└┘┴ ┴└┘┴└┘┴
src └──┘ └┘ └┘ └┘ └┘
typ └──┘ ┴└┘┴└┘┴ ┴└┘┴└┘┴
20 | trans : Π {l₁ l₂ l₃ : list α}, perm l₁ l₂ → perm l₂ l₃ → perm l₁ l₃
id └──┘ └──┘ └┘ └┘ └──┘ └┘ └┘ └┘ └┘
src └──┘
typ └──┘ └──┘ └┘ └┘ └──┘ └┘ └┘ └┘ └┘
21 open perm
22
23 infix ~ := perm
id └──┘
src └──┘
typ └──┘
doc └──┘
24
25 @[refl] protected theorem perm.refl : ∀ (l : list α), l ~ l
id ┴ └──┘ ┴ ┴ ┴ ┴
src └──┘ └──┘ ┴
typ ┴ └──┘ ┴ ┴ ┴ ┴
doc └──┘ ┴
26 | [] := perm.nil
id └┘ └──────┘
src └┘ └──────┘
typ └┘ └──────┘
27 | (x::xs) := skip x (perm.refl xs)
id ┴└┘└┘ └──┘ └───────┘
src └┘ └──┘
typ ┴└┘└┘ └──┘ └───────┘
28
29 @[symm] protected theorem perm.symm {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₂ ~ l₁ :=
id └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘
src └──┘ └──┘ ┴ ┴
typ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘
doc └──┘ ┴ ┴
30 perm.rec_on p
id └─────────┘ ┴
src └─────────┘
typ └─────────┘ ┴
31 perm.nil
id └──────┘
src └──────┘
typ └──────┘
32 (λ x l₁ l₂ p₁ r₁, skip x r₁)
id ┴ └┘ └┘ └┘ └┘ └──┘ ┴ └┘
src └──┘
typ ┴ └┘ └┘ └┘ └┘ └──┘ ┴ └┘
33 (λ x y l, swap y x l)
id ┴ ┴ ┴ └──┘ ┴ ┴ ┴
src └──┘
typ ┴ ┴ ┴ └──┘ ┴ ┴ ┴
34 (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂, trans r₂ r₁)
id └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘ └┘ └┘
src └───┘
typ └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘ └┘ └┘
35
36 theorem perm.swap'
37 (x y : α) {l₁ l₂ : list α} (p : l₁ ~ l₂) : y::x::l₁ ~ x::y::l₂ :=
id ┴ └──┘ ┴ └┘ ┴ └┘ ┴└┘┴└┘└┘ ┴ ┴└┘┴└┘└┘
src └──┘ ┴ └┘ └┘ ┴ └┘ └┘
typ ┴ └──┘ ┴ └┘ ┴ └┘ ┴└┘┴└┘└┘ ┴ ┴└┘┴└┘└┘
doc ┴ ┴
38 trans (swap _ _ _) (skip _ $ skip _ p)
id └───┘ └──┘ └──┘ └──┘ ┴
src └───┘ └──┘ └──┘ └──┘
typ └───┘ └──┘ └──┘ └──┘ ┴
39
40 attribute [trans] perm.trans
id └────────┘
src └───┘ └────────┘
typ └────────┘
doc └───┘
41
42 theorem perm.eqv (α) : equivalence (@perm α) :=
id └─────────┘ └──┘ ┴
src └─────────┘ └──┘
typ └─────────┘ └──┘ ┴
doc └──┘
43 mk_equivalence (@perm α) (@perm.refl α) (@perm.symm α) (@perm.trans α)
id └────────────┘ └──┘ ┴ └───────┘ ┴ └───────┘ ┴ └────────┘ ┴
src └────────────┘ └──┘ └───────┘ └───────┘ └────────┘
typ └────────────┘ └──┘ ┴ └───────┘ ┴ └───────┘ ┴ └────────┘ ┴
doc └──┘
44
45 instance is_setoid (α) : setoid (list α) :=
id └────┘ └──┘ ┴
src └────┘ └──┘
typ └────┘ └──┘ ┴
46 setoid.mk (@perm α) (perm.eqv α)
id └───────┘ └──┘ ┴ └──────┘ ┴
src └───────┘ └──┘ └──────┘
typ └───────┘ └──┘ ┴ └──────┘ ┴
doc └──┘
47
48 theorem perm_subset {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ :=
id └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘
src └──┘ ┴ ┴
typ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘
doc ┴
49 λ a, perm.rec_on p
id ┴ └─────────┘ ┴
src └─────────┘
typ ┴ └─────────┘ ┴
50 (λ h, h)
id ┴ ┴
typ ┴ ┴
51 (λ x l₁ l₂ p₁ r₁ i, or.elim i
id ┴ └┘ └┘ └┘ └┘ ┴ └─────┘ ┴
src └─────┘
typ ┴ └┘ └┘ └┘ └┘ ┴ └─────┘ ┴
52 (λ ax, by simp [ax])
id └┘ └┘
src └────┘ ┴
typ └┘ └────┘└┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └────────┘
53 (λ al₁, or.inr (r₁ al₁)))
id └─┘ └────┘ └┘ └─┘
src └────┘
typ └─┘ └────┘ └┘ └─┘
54 (λ x y l ayxl, or.elim ayxl
id ┴ ┴ ┴ └──┘ └─────┘ └──┘
src └─────┘
typ ┴ ┴ ┴ └──┘ └─────┘ └──┘
55 (λ ay, by simp [ay])
id └┘ └┘
src └────┘ ┴
typ └┘ └────┘└┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └────────┘
56 (λ axl, or.elim axl
id └─┘ └─────┘ └─┘
src └─────┘
typ └─┘ └─────┘ └─┘
57 (λ ax, by simp [ax])
id └┘ └┘
src └────┘ ┴
typ └┘ └────┘└┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴┴ ┴
st └────────┘
58 (λ al, or.inr (or.inr al))))
id └┘ └────┘ └────┘ └┘
src └────┘ └────┘
typ └┘ └────┘ └────┘ └┘
59 (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂ ainl₁, r₂ (r₁ ainl₁))
id └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘ └┘ └┘ └───┘
typ └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘ └┘ └┘ └───┘
60
61 theorem mem_of_perm {a : α} {l₁ l₂ : list α} (h : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
id ┴ └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
src └──┘ ┴ ┴ ┴ ┴
typ ┴ └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
doc ┴
62 iff.intro (λ m, perm_subset h m) (λ m, perm_subset h.symm m)
id └───────┘ ┴ └─────────┘ ┴ ┴ ┴ └─────────┘ ┴└───┘ ┴
src └───────┘ └─────────┘ └─────────┘ └───┘
typ └───────┘ ┴ └─────────┘ ┴ ┴ ┴ └─────────┘ ┴└───┘ ┴
63
64 theorem perm_app_left {l₁ l₂ : list α} (t₁ : list α) (p : l₁ ~ l₂) : l₁++t₁ ~ l₂++t₁ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘└┘└┘ ┴ └┘└┘└┘
src └──┘ └──┘ ┴ └┘ ┴ └┘
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘└┘└┘ ┴ └┘└┘└┘
doc ┴ ┴
65 perm.rec_on p
id └─────────┘ ┴
src └─────────┘
typ └─────────┘ ┴
66 (perm.refl ([] ++ t₁))
id └───────┘ └┘ └┘ └┘
src └───────┘ └┘ └┘
typ └───────┘ └┘ └┘ └┘
67 (λ x l₁ l₂ p₁ r₁, skip x r₁)
id ┴ └┘ └┘ └┘ └┘ └──┘ ┴ └┘
src └──┘
typ ┴ └┘ └┘ └┘ └┘ └──┘ ┴ └┘
68 (λ x y l, swap x y _)
id ┴ ┴ ┴ └──┘ ┴ ┴
src └──┘
typ ┴ ┴ ┴ └──┘ ┴ ┴
69 (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂, trans r₁ r₂)
id └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘ └┘ └┘
src └───┘
typ └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘ └┘ └┘
70
71 theorem perm_app_right {t₁ t₂ : list α} : ∀ (l : list α), t₁ ~ t₂ → l++t₁ ~ l++t₂
id └──┘ ┴ ┴ └──┘ ┴ └┘ ┴ └┘ ┴└┘└┘ ┴ ┴└┘└┘
src └──┘ └──┘ ┴ └┘ ┴ └┘
typ └──┘ ┴ ┴ └──┘ ┴ └┘ ┴ └┘ ┴└┘└┘ ┴ ┴└┘└┘
doc ┴ ┴
72 | [] p := p
id └┘ ┴
src └┘
typ └┘ ┴
73 | (x::xs) p := skip x (perm_app_right xs p)
id ┴└┘└┘ ┴ └──┘ └────────────┘
src └┘ └──┘
typ ┴└┘└┘ ┴ └──┘ └────────────┘
74
75 theorem perm_app {l₁ l₂ t₁ t₂ : list α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁++t₁ ~ l₂++t₂ :=
id └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘└┘└┘ ┴ └┘└┘└┘
src └──┘ ┴ ┴ └┘ ┴ └┘
typ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘└┘└┘ ┴ └┘└┘└┘
doc ┴ ┴ ┴
76 trans (perm_app_left t₁ p₁) (perm_app_right l₂ p₂)
id └───┘ └───────────┘ └┘ └┘ └────────────┘ └┘ └┘
src └───┘ └───────────┘ └────────────┘
typ └───┘ └───────────┘ └┘ └┘ └────────────┘ └┘ └┘
77
78 theorem perm_app_cons (a : α) {h₁ h₂ t₁ t₂ : list α}
id ┴ └──┘ ┴
src └──┘
typ ┴ └──┘ ┴
79 (p₁ : h₁ ~ h₂) (p₂ : t₁ ~ t₂) : h₁ ++ a::t₁ ~ h₂ ++ a::t₂ :=
id └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ ┴└┘└┘ ┴ └┘ └┘ ┴└┘└┘
src ┴ ┴ └┘ └┘ ┴ └┘ └┘
typ └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ ┴└┘└┘ ┴ └┘ └┘ ┴└┘└┘
doc ┴ ┴ ┴
80 perm_app p₁ (skip a p₂)
id └──────┘ └┘ └──┘ ┴ └┘
src └──────┘ └──┘
typ └──────┘ └┘ └──┘ ┴ └┘
81
82 @[simp] theorem perm_middle {a : α} : ∀ {l₁ l₂ : list α}, l₁++a::l₂ ~ a::(l₁++l₂)
id ┴ ┴ └──┘ ┴ └┘└┘┴└┘└┘ ┴ ┴└┘ └┘└┘└┘
src └──┘ └┘ └┘ ┴ └┘ └┘
typ ┴ ┴ └──┘ ┴ └┘└┘┴└┘└┘ ┴ ┴└┘ └┘└┘└┘
doc └──┘ ┴
83 | [] l₂ := perm.refl _
id └┘ └───────┘
src └┘ └───────┘
typ └┘ └───────┘
84 | (b::l₁) l₂ := (skip b (@perm_middle l₁ l₂)).trans (swap a b _)
id ┴└┘└┘ └┘ └──┘ └─────────┘ └───┘ └──┘ ┴
src └┘ └──┘ └───┘ └──┘
typ ┴└┘└┘ └┘ └──┘ └─────────┘ └───┘ └──┘ ┴
85
86 @[simp] theorem perm_cons_app (a : α) (l : list α) : l ++ [a] ~ a::l :=
id ┴ └──┘ ┴ ┴ └┘ ┴┴┴ ┴ ┴└┘┴
src └──┘ └┘ ┴ ┴ ┴ └┘
typ ┴ └──┘ ┴ ┴ └┘ ┴┴┴ ┴ ┴└┘┴
doc └──┘ ┴
87 by simpa using @perm_middle _ a l []
id └─────────┘ ┴ ┴ └┘
src └──────────┘ └─────────┘└─┘ ┴ ┴└┘└
typ └──────────┘ └─────────┘└─┘┴┴┴┴└┘└
doc └──────────┘ └─┘ ┴ ┴ └
txt └──────────┘ └─┘ ┴ ┴ └
par └──────────┘ └─┘ ┴ ┴ └
pid ┴└────┘ └─┘ ┴ ┴ └
st └──────────────────────────────────
88
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
89 @[simp] theorem perm_app_comm : ∀ {l₁ l₂ : list α}, (l₁++l₂) ~ (l₂++l₁)
id ┴ └──┘ ┴ └┘└┘└┘ ┴ └┘└┘└┘
src └──┘ └┘ ┴ └┘
typ ┴ └──┘ ┴ └┘└┘└┘ ┴ └┘└┘└┘
doc └──┘ ┴
90 | [] l₂ := by simp
id └┘
src └┘ └───┘
typ └┘ └───┘
doc └───┘
txt └───┘
par └───┘
pid ┴
st └────┘
91 | (a::t) l₂ := (skip a perm_app_comm).trans perm_middle.symm
id ┴└┘ └──┘ └───────────┘ └───┘ └─────────┘└───┘
src └┘ └──┘ └───┘ └─────────┘└───┘
typ ┴└┘ └──┘ └───────────┘ └───┘ └─────────┘└───┘
92
93 theorem concat_perm (l : list α) (a : α) : concat l a ~ a :: l :=
id └──┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ └┘ ┴
src └──┘ └────┘ ┴ └┘
typ └──┘ ┴ ┴ └────┘ ┴ ┴ ┴ ┴ └┘ ┴
doc └────┘ ┴
94 by simp
src └────
typ └────
doc └────
txt └────
par └────
pid └
st └─────
95
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
96 theorem perm_length {l₁ l₂ : list α} (p : l₁ ~ l₂) : length l₁ = length l₂ :=
id └──┘ ┴ └┘ ┴ └┘ └────┘ └┘ ┴ └────┘ └┘
src └──┘ ┴ └────┘ ┴ └────┘
typ └──┘ ┴ └┘ ┴ └┘ └────┘ └┘ ┴ └────┘ └┘
doc ┴
97 perm.rec_on p
id └─────────┘ ┴
src └─────────┘
typ └─────────┘ ┴
98 rfl
id └─┘
src └─┘
typ └─┘
99 (λ x l₁ l₂ p r, by simp[r])
id ┴ └┘ └┘ ┴ ┴ ┴
src └───┘ ┴
typ ┴ └┘ └┘ ┴ ┴ └───┘┴┴
doc └───┘ ┴
txt └───┘ ┴
par └───┘ ┴
pid ┴ ┴
st └──────┘
100 (λ x y l, by simp)
id ┴ ┴ ┴
src └──┘
typ ┴ ┴ ┴ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
101 (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂, eq.trans r₁ r₂)
id └┘ └┘ └┘ └┘ └┘ └┘ └┘ └──────┘ └┘ └┘
src └──────┘
typ └┘ └┘ └┘ └┘ └┘ └┘ └┘ └──────┘ └┘ └┘
102
103 theorem eq_nil_of_perm_nil {l₁ : list α} (p : [] ~ l₁) : l₁ = [] :=
id └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘
src └──┘ └┘ ┴ ┴ └┘
typ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘
doc ┴
104 eq_nil_of_length_eq_zero (perm_length p).symm
id └──────────────────────┘ └─────────┘ ┴ └──┘
src └──────────────────────┘ └─────────┘ └──┘
typ └──────────────────────┘ └─────────┘ ┴ └──┘
105
106 theorem perm_nil {l₁ : list α} : l₁ ~ [] ↔ l₁ = [] :=
id └──┘ ┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘
src └──┘ ┴ └┘ ┴ ┴ └┘
typ └──┘ ┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘
doc ┴
107 ⟨λ p, eq_nil_of_perm_nil p.symm, λ e, e ▸ perm.refl _⟩
id ┴ └────────────────┘ ┴└───┘ ┴ ┴ ┴ └───────┘
src └────────────────┘ └───┘ ┴ └───────┘
typ ┴ └────────────────┘ ┴└───┘ ┴ ┴ ┴ └───────┘
108
109 theorem not_perm_nil_cons (x : α) (l : list α) : ¬ [] ~ x::l
id ┴ └──┘ ┴ ┴ └┘ ┴ ┴└┘┴
src └──┘ ┴ └┘ ┴ └┘
typ ┴ └──┘ ┴ ┴ └┘ ┴ ┴└┘┴
doc ┴
110 | p := by injection eq_nil_of_perm_nil p
id └────────────────┘ ┴
src └────────┘└────────────────┘┴ └
typ └────────┘└────────────────┘┴┴└
doc └────────┘ ┴ └
txt └────────┘ ┴ └
par └────────┘ ┴ └
pid ┴ ┴ └
st └───────────────────────────────
111
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
112 theorem eq_singleton_of_perm {a b : α} (p : [a] ~ [b]) : a = b :=
id ┴ ┴┴┴ ┴ ┴┴┴ ┴ ┴ ┴
src ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ ┴┴┴ ┴ ┴┴┴ ┴ ┴ ┴
doc ┴
113 by simpa using perm_subset p (by simp)
id └─────────┘ ┴
src └──────────┘└─────────┘┴ ┴ ┴└──┘└─
typ └──────────┘└─────────┘┴┴┴ ┴└──┘└─
doc └──────────┘ ┴ ┴ ┴└──┘└─
txt └──────────┘ ┴ ┴ ┴└──┘└─
par └──────────┘ ┴ ┴ ┴└──┘└─
pid ┴└────┘ ┴ ┴ └────┘└
st └────────────────────────────┘└───┘└─
114
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
115 theorem eq_singleton_of_perm_inv {a : α} {l : list α} (p : [a] ~ l) : l = [a] :=
id ┴ └──┘ ┴ ┴┴┴ ┴ ┴ ┴ ┴ ┴┴┴
src └──┘ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ └──┘ ┴ ┴┴┴ ┴ ┴ ┴ ┴ ┴┴┴
doc ┴
116 match l, show 1 = _, from perm_length p, p with
id ┴ ┴ └─────────┘ ┴ ┴
src ┴ └─────────┘
typ ┴ ┴ └─────────┘ ┴ ┴
117 | [a'], rfl, p := by rw [eq_singleton_of_perm p]
id ┴ ┴ └─┘ └──────────────────┘ ┴
src ┴ ┴ └─┘ └──┘└──────────────────┘┴ └┘
typ ┴ ┴ └─┘ └──┘└──────────────────┘┴┴└┘
doc └──┘ ┴ └┘
txt └──┘ ┴ └┘
par └──┘ ┴ └┘
pid └┘ ┴ ┴┴
st └─────────────────────────┘┴┴
118 end
119
120 @[simp] theorem reverse_perm : ∀ (l : list α), reverse l ~ l
id ┴ └──┘ ┴ └─────┘ ┴ ┴ ┴
src └──┘ └─────┘ ┴
typ ┴ └──┘ ┴ └─────┘ ┴ ┴ ┴
doc └──┘ ┴
121 | [] := perm.nil
id └┘ └──────┘
src └┘ └──────┘
typ └┘ └──────┘
122 | (a::l) := by rw reverse_cons; exact
id └┘ └──────────┘
src └┘ └─┘└──────────┘ └─────
typ └┘ └─┘└──────────┘ └─────
doc └─┘ └─────
txt └─┘ └─────
par └─┘ └─────
pid ┴ └
st └───────────────────────
123 (perm_cons_app _ _).trans (skip a $ reverse_perm l)
id └───────────┘ └──┘ ┴ └──────────┘ ┴
src ─┘ └───────────┘└──────────┘ └──┘┴ ┴ ┴ ┴ └─
typ ─┘ └───────────┘└──────────┘ └──┘┴┴┴ ┴└──────────┘┴┴└─
doc ─┘ └──────────┘ ┴ ┴ ┴ ┴ └─
txt ─┘ └──────────┘ ┴ ┴ ┴ ┴ └─
par ─┘ └──────────┘ ┴ ┴ ┴ ┴ └─
pid ─┘ └──────────┘ ┴ ┴ ┴ ┴ ┴└
st ──────────────────────────────────────────────────────
124
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
125 theorem perm_cons_app_cons {l l₁ l₂ : list α} (a : α) (p : l ~ l₁++l₂) : a::l ~ l₁++(a::l₂) :=
id └──┘ ┴ ┴ ┴ ┴ └┘└┘└┘ ┴└┘┴ ┴ └┘└┘ ┴└┘└┘
src └──┘ ┴ └┘ └┘ ┴ └┘ └┘
typ └──┘ ┴ ┴ ┴ ┴ └┘└┘└┘ ┴└┘┴ ┴ └┘└┘ ┴└┘└┘
doc ┴ ┴
126 trans (skip a p) perm_middle.symm
id └───┘ └──┘ ┴ ┴ └─────────┘└───┘
src └───┘ └──┘ └─────────┘└───┘
typ └───┘ └──┘ ┴ ┴ └─────────┘└───┘
127
128 @[simp] theorem perm_repeat {a : α} {n : ℕ} {l : list α} : repeat a n ~ l ↔ repeat a n = l :=
id ┴ ┴ └──┘ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴
src ┴ └──┘ └────┘ ┴ ┴ └────┘ ┴
typ ┴ ┴ └──┘ ┴ └────┘ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ ┴ ┴
doc └──┘ ┴
129 ⟨λ p, (eq_repeat.2 $ by exact
id ┴ └───────┘┴
src └───────┘┴ └─────
typ ┴ └───────┘┴ └─────
doc └─────
txt └─────
par └─────
pid └
st └──────
130 ⟨by simpa using (perm_length p).symm,
id └─────────┘ ┴
src ─┘ ┴└──────────┘ └─────────┘┴ └────┘└─
typ ─┘ ┴└──────────┘ └─────────┘┴┴└────┘└─
doc ─┘ ┴└──────────┘ ┴ └────┘└─
txt ─┘ ┴└──────────┘ ┴ └────┘└─
par ─┘ ┴└──────────┘ ┴ └────┘└─
pid ─┘ └───────────┘ ┴ └───────
st ────┘└───────────────────────────────┘└─
131 λ b m, eq_of_mem_repeat $ perm_subset p.symm m⟩).symm,
id └──────────────┘ └─────────┘ └────┘ └──┘
src ──┘ └────┘└──────────────┘┴ ┴└─────────┘┴└────┘┴ ┴ └──┘
typ ──┘ └────┘└──────────────┘┴ ┴└─────────┘┴└────┘┴ ┴ └──┘
doc ──┘ └────┘ ┴ ┴ ┴ ┴ ┴
txt ──┘ └────┘ ┴ ┴ ┴ ┴ ┴
par ──┘ └────┘ ┴ ┴ ┴ ┴ ┴
pid ──┘ └────┘ ┴ ┴ ┴ ┴ ┴
st ─────────────────────────────────────────────────┘
132 λ h, h ▸ perm.refl _⟩
id ┴ ┴ ┴ └───────┘
src ┴ └───────┘
typ ┴ ┴ ┴ └───────┘
133
134 theorem perm_erase [decidable_eq α] {a : α} {l : list α} (h : a ∈ l) : l ~ a :: l.erase a :=
id └──────────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴└────┘ ┴
src └──────────┘ └──┘ ┴ ┴ └┘ └────┘
typ └──────────┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴└────┘ ┴
doc ┴
135 let ⟨l₁, l₂, _, e₁, e₂⟩ := exists_erase_eq h in
id └─┘ └┘ └┘ └─────────────┘ ┴
src └─────────────┘
typ └─┘ └┘ └┘ └─────────────┘ ┴
136 e₂.symm ▸ e₁.symm ▸ perm_middle
id └───┘ ┴ └───┘ ┴ └─────────┘
src └───┘ ┴ └───┘ ┴ └─────────┘
typ └───┘ ┴ └───┘ ┴ └─────────┘
137
138 @[elab_as_eliminator] theorem perm_induction_on
doc └────────────────┘
139 {P : list α → list α → Prop} {l₁ l₂ : list α} (p : l₁ ~ l₂)
id └──┘ ┴ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘
src └──┘ └──┘ └──┘ ┴
typ └──┘ ┴ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘
doc ┴
140 (h₁ : P [] [])
id ┴ └┘ └┘
src └┘ └┘
typ ┴ └┘ └┘
141 (h₂ : ∀ x l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (x::l₁) (x::l₂))
id ┴ └┘ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴└┘└┘ ┴└┘└┘
src ┴ └┘ └┘
typ ┴ └┘ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴└┘└┘ ┴└┘└┘
doc ┴
142 (h₃ : ∀ x y l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (y::x::l₁) (x::y::l₂))
id ┴ ┴ └┘ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴└┘┴└┘└┘ ┴└┘┴└┘└┘
src ┴ └┘ └┘ └┘ └┘
typ ┴ ┴ └┘ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴└┘┴└┘└┘ ┴└┘┴└┘└┘
doc ┴
143 (h₄ : ∀ l₁ l₂ l₃, l₁ ~ l₂ → l₂ ~ l₃ → P l₁ l₂ → P l₂ l₃ → P l₁ l₃) :
id └┘ └┘ └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ ┴ └┘ └┘
src ┴ ┴
typ └┘ └┘ └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ ┴ └┘ └┘
doc ┴ ┴
144 P l₁ l₂ :=
id ┴ └┘ └┘
typ ┴ └┘ └┘
145 have P_refl : ∀ l, P l l, from
id ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴
146 assume l,
id ┴
typ ┴
147 list.rec_on l h₁ (λ x xs ih, h₂ x xs xs (perm.refl xs) ih),
id └─────────┘ ┴ └┘ ┴ └┘ └┘ └┘ ┴ └┘ └┘ └───────┘ └┘ └┘
src └─────────┘ └───────┘
typ └─────────┘ ┴ └┘ ┴ └┘ └┘ └┘ ┴ └┘ └┘ └───────┘ └┘ └┘
148 perm.rec_on p h₁ h₂ (λ x y l, h₃ x y l l (perm.refl l) (P_refl l)) h₄
id └─────────┘ ┴ └┘ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └───────┘ ┴ └────┘ ┴ └┘
src └─────────┘ └───────┘
typ └─────────┘ ┴ └┘ └┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └───────┘ ┴ └────┘ ┴ └┘
149
150 @[congr] theorem perm_filter_map (f : α → option β) {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id ┴ └────┘ ┴ └──┘ ┴ └┘ ┴ └┘
src └───┘ └────┘ └──┘ ┴
typ ┴ └────┘ ┴ └──┘ ┴ └┘ ┴ └┘
doc └───┘ ┴
151 filter_map f l₁ ~ filter_map f l₂ :=
id └────────┘ ┴ └┘ ┴ └────────┘ ┴ └┘
src └────────┘ ┴ └────────┘
typ └────────┘ ┴ └┘ ┴ └────────┘ ┴ └┘
doc ┴
152 begin
st └─────
153 induction p with x l₂ l₂' p IH x y l₂ l₂ m₂ r₂ p₁ p₂ IH₁ IH₂,
id ┴
src └────────┘ └─────────────────────────────────────────────────┘
typ └────────┘┴└─────────────────────────────────────────────────┘
doc └────────┘ └─────────────────────────────────────────────────┘
txt └────────┘ └─────────────────────────────────────────────────┘
par └────────┘ └─────────────────────────────────────────────────┘
pid ┴ ┴└────────────────────────────────────────────────┘
st ───────────────────────────────────────────────────────────────┘└─
154 { simp },
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
pid ┴
st ───┘└───┘└┘└
155 { simp [filter_map], cases f x with a; simp [filter_map, IH, skip] },
id └────────┘ ┴ ┴ └────────┘ └┘ └──┘
src └────┘└────────┘┴ └────┘ ┴ └─────┘ └────┘└────────┘└┘ └┘└──┘└┘
typ └────┘└────────┘┴ └────┘┴┴┴└─────┘ └────┘└────────┘└┘└┘└┘└──┘└┘
doc └────┘ ┴ └────┘ ┴ └─────┘ └────┘ └┘ └┘ └┘
txt └────┘ ┴ └────┘ ┴ └─────┘ └────┘ └┘ └┘ └┘
par └────┘ ┴ └────┘ ┴ └─────┘ └────┘ └┘ └┘ └┘
pid ┴┴ ┴ ┴ ┴ └─────┘ ┴┴ └┘ └┘ ┴┴
st ───┘└───────────────┘└──────────────────────────────────────────────┘└┘└
156 { simp [filter_map], cases f x with a; cases f y with b; simp [filter_map, swap] },
id └────────┘ ┴ ┴ ┴ ┴ └────────┘ └──┘
src └────┘└────────┘┴ └────┘ ┴ └─────┘ └────┘ ┴ └─────┘ └────┘└────────┘└┘└──┘└┘
typ └────┘└────────┘┴ └────┘┴┴┴└─────┘ └────┘┴┴┴└─────┘ └────┘└────────┘└┘└──┘└┘
doc └────┘ ┴ └────┘ ┴ └─────┘ └────┘ ┴ └─────┘ └────┘ └┘ └┘
txt └────┘ ┴ └────┘ ┴ └─────┘ └────┘ ┴ └─────┘ └────┘ └┘ └┘
par └────┘ ┴ └────┘ ┴ └─────┘ └────┘ ┴ └─────┘ └────┘ └┘ └┘
pid ┴┴ ┴ ┴ ┴ └─────┘ ┴ ┴ └─────┘ ┴┴ └┘ ┴┴
st ───┘└───────────────┘└────────────────────────────────────────────────────────────┘└┘└
157 { exact IH₁.trans IH₂ }
id └───────┘ └─┘
src └────┘└───────┘┴ ┴
typ └────┘└───────┘┴└─┘┴
doc └────┘ ┴ ┴
txt └────┘ ┴ ┴
par └────┘ ┴ ┴
pid ┴ ┴ ┴
st ───────────────────────┘└─
158 end
st ──┘
159
160 @[congr] theorem perm_map (f : α → β) {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id ┴ ┴ └──┘ ┴ └┘ ┴ └┘
src └───┘ └──┘ ┴
typ ┴ ┴ └──┘ ┴ └┘ ┴ └┘
doc └───┘ ┴
161 map f l₁ ~ map f l₂ :=
id └─┘ ┴ └┘ ┴ └─┘ ┴ └┘
src └─┘ ┴ └─┘
typ └─┘ ┴ └┘ ┴ └─┘ ┴ └┘
doc ┴
162 by rw ← filter_map_eq_map; apply perm_filter_map _ p
id └───────────────┘ └─────────────┘ ┴
src └───┘└───────────────┘ └────┘└─────────────┘└─┘ └
typ └───┘└───────────────┘ └────┘└─────────────┘└─┘┴└
doc └───┘ └────┘ └─┘ └
txt └───┘ └────┘ └─┘ └
par └───┘ └────┘ └─┘ └
pid └─┘ ┴ └─┘ └
st └──────────────────────────────────────────────────
163
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
164 theorem perm_pmap {p : α → Prop} (f : Π a, p a → β)
id ┴ ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴ ┴
165 {l₁ l₂ : list α} (p : l₁ ~ l₂) {H₁ H₂} : pmap f l₁ H₁ ~ pmap f l₂ H₂ :=
id └──┘ ┴ └┘ ┴ └┘ └──┘ ┴ └┘ └┘ ┴ └──┘ ┴ └┘ └┘
src └──┘ ┴ └──┘ ┴ └──┘
typ └──┘ ┴ └┘ ┴ └┘ └──┘ ┴ └┘ └┘ ┴ └──┘ ┴ └┘ └┘
doc ┴ └──┘ ┴ └──┘
166 begin
st └─────
167 induction p with x l₂ l₂' p IH x y l₂ l₂ m₂ r₂ p₁ p₂ IH₁ IH₂,
id ┴
src └────────┘ └─────────────────────────────────────────────────┘
typ └────────┘┴└─────────────────────────────────────────────────┘
doc └────────┘ └─────────────────────────────────────────────────┘
txt └────────┘ └─────────────────────────────────────────────────┘
par └────────┘ └─────────────────────────────────────────────────┘
pid ┴ ┴└────────────────────────────────────────────────┘
st ───────────────────────────────────────────────────────────────┘└─
168 { simp },
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
pid ┴
st ───┘└───┘└┘└
169 { simp [IH, skip] },
id └──┘
src └────┘ └┘└──┘└┘
typ └────┘└┘└┘└──┘└┘
doc └────┘ └┘ └┘
txt └────┘ └┘ └┘
par └────┘ └┘ └┘
pid ┴┴ └┘ ┴┴
st ───┘└──────────────┘└┘└
170 { simp [swap] },
id └──┘
src └────┘└──┘└┘
typ └────┘└──┘└┘
doc └────┘ └┘
txt └────┘ └┘
par └────┘ └┘
pid ┴┴ ┴┴
st ───┘└──────────┘└┘└
171 { refine IH₁.trans IH₂,
id └───────┘ └─┘
src └─────┘└───────┘┴
typ └─────┘└───────┘┴└─┘
doc └─────┘ ┴
txt └─────┘ ┴
par └─────┘ ┴
pid ┴ ┴
st ───────────────────────┘└─
172 exact λ a m, H₂ a (perm_subset p₂ m) }
id └┘ └─────────┘ └┘
src └────┘ └────┘ ┴ ┴ └─────────┘┴ ┴ └┘
typ └────┘ └────┘└┘┴ ┴ └─────────┘┴└┘┴ └┘
doc └────┘ └────┘ ┴ ┴ ┴ ┴ └┘
txt └────┘ └────┘ ┴ ┴ ┴ ┴ └┘
par └────┘ └────┘ ┴ ┴ ┴ ┴ └┘
pid ┴ └────┘ ┴ ┴ ┴ ┴ ┴┴
st ────────────────────────────────────────┘└─
173 end
st ──┘
174
175 theorem perm_filter (p : α → Prop) [decidable_pred p]
id ┴ └────────────┘ ┴
src └────────────┘
typ ┴ └────────────┘ ┴
176 {l₁ l₂ : list α} (s : l₁ ~ l₂) : filter p l₁ ~ filter p l₂ :=
id └──┘ ┴ └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
src └──┘ ┴ └────┘ ┴ └────┘
typ └──┘ ┴ └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
doc ┴ ┴
177 by rw ← filter_map_eq_filter; apply perm_filter_map _ s
id └──────────────────┘ └─────────────┘ ┴
src └───┘└──────────────────┘ └────┘└─────────────┘└─┘ └
typ └───┘└──────────────────┘ └────┘└─────────────┘└─┘┴└
doc └───┘ └────┘ └─┘ └
txt └───┘ └────┘ └─┘ └
par └───┘ └────┘ └─┘ └
pid └─┘ ┴ └─┘ └
st └─────────────────────────────────────────────────────
178
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
179 theorem exists_perm_sublist {l₁ l₂ l₂' : list α}
id └──┘ ┴
src └──┘
typ └──┘ ┴
180 (s : l₁ <+ l₂) (p : l₂ ~ l₂') : ∃ l₁' ~ l₁, l₁' <+ l₂' :=
id └┘ └┘ └┘ └┘ ┴ └─┘ ┴ └─┘ └┘┴ └─┘ └┘ └─┘
src └┘ ┴ ┴ ┴ └┘
typ └┘ └┘ └┘ └┘ ┴ └─┘ ┴ └─┘ └┘┴ └─┘ └┘ └─┘
doc ┴
181 begin
st └─────
182 induction p with x l₂ l₂' p IH x y l₂ l₂ m₂ r₂ p₁ p₂ IH₁ IH₂ generalizing l₁ s,
id ┴
src └────────┘ └───────────────────────────────────────────────────────────────────┘
typ └────────┘┴└───────────────────────────────────────────────────────────────────┘
doc └────────┘ └───────────────────────────────────────────────────────────────────┘
txt └────────┘ └───────────────────────────────────────────────────────────────────┘
par └────────┘ └───────────────────────────────────────────────────────────────────┘
pid ┴ ┴└────────────────────────────────────────────────┘└────────────────┘
st ─────────────────────────────────────────────────────────────────────────────────┘└─
183 { exact ⟨[], eq_nil_of_sublist_nil s ▸ perm.refl _, nil_sublist _⟩ },
id └───────────────────┘ ┴ ┴ └───────┘ └─────────┘
src └────┘ └┘└───────────────────┘┴ ┴┴┴└───────┘└──┘└─────────┘└──┘
typ └────┘ └┘└───────────────────┘┴┴┴┴┴└───────┘└──┘└─────────┘└──┘
doc └────┘ └┘ ┴ ┴ ┴ └──┘ └──┘
txt └────┘ └┘ ┴ ┴ ┴ └──┘ └──┘
par └────┘ └┘ ┴ ┴ ┴ └──┘ └──┘
pid ┴ └┘ ┴ ┴ ┴ └──┘ └─┘┴
st ───┘└───────────────────────────────────────────────────────────────┘└┘└
184 { cases s with _ _ _ s l₁ _ _ s,
id ┴
src └────┘ └────────────────────┘
typ └────┘┴└────────────────────┘
doc └────┘ └────────────────────┘
txt └────┘ └────────────────────┘
par └────┘ └────────────────────┘
pid ┴ └────────────────────┘
st ───┘└───────────────────────────┘└─
185 { exact let ⟨l₁', p', s'⟩ := IH s in ⟨l₁', p', s'.cons _ _ _⟩ },
id └─┘ └┘ └┘ └┘ ┴ └───┘
src └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ └┘ └───┘└──────┘
typ └────┘ ┴ └─┘└┘└┘└┘└┘└───┘└┘┴┴└──┘ └┘ └┘ └───┘└──────┘
doc └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ └┘ └──────┘
txt └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ └┘ └──────┘
par └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ └┘ └──────┘
pid ┴ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ └┘ └─────┘┴
st ─────┘└──────────────────────────────────────────────────────────┘└┘└
186 { exact let ⟨l₁', p', s'⟩ := IH s in ⟨x::l₁', skip x p', s'.cons2 _ _ _⟩ } },
id └─┘ └┘ └┘ └┘ ┴ └──┘ ┴ └────┘
src └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘└──┘┴ ┴ └┘ └────┘└──────┘
typ └────┘ ┴ └─┘└┘└┘└┘└┘└───┘└┘┴┴└──┘ └┘└──┘┴┴┴ └┘ └────┘└──────┘
doc └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ ┴ ┴ └┘ └──────┘
txt └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ ┴ ┴ └┘ └──────┘
par └────┘ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ ┴ ┴ └┘ └──────┘
pid ┴ ┴ └┘ └┘ └───┘ ┴ └──┘ └┘ ┴ ┴ └┘ └─────┘┴
st ────────────────────────────────────────────────────────────────────────────┘└──┘└
187 { cases s with _ _ _ s l₁ _ _ s; cases s with _ _ _ s l₁ _ _ s,
id ┴ ┴
src └────┘ └────────────────────┘ └────┘ └────────────────────┘
typ └────┘┴└────────────────────┘ └────┘┴└────────────────────┘
doc └────┘ └────────────────────┘ └────┘ └────────────────────┘
txt └────┘ └────────────────────┘ └────┘ └────────────────────┘
par └────┘ └────────────────────┘ └────┘ └────────────────────┘
pid ┴ └────────────────────┘ ┴ └────────────────────┘
st ───┘└──────────────────────────────────────────────────────────┘└─
188 { exact ⟨l₁, perm.refl _, (s.cons _ _ _).cons _ _ _⟩ },
id └┘ └───────┘ └────┘
src └────┘ └┘└───────┘└──┘ └────┘└──────────────────┘
typ └────┘ └┘└┘└───────┘└──┘ └────┘└──────────────────┘
doc └────┘ └┘ └──┘ └──────────────────┘
txt └────┘ └┘ └──┘ └──────────────────┘
par └────┘ └┘ └──┘ └──────────────────┘
pid ┴ └┘ └──┘ └─────────────────┘┴
st ─────┘└─────────────────────────────────────────────────┘└┘└
189 { exact ⟨x::l₁, perm.refl _, (s.cons _ _ _).cons2 _ _ _⟩ },
id ┴ └┘ └───────┘ └────┘
src └────┘ └┘└───────┘└──┘ └────┘└───────────────────┘
typ └────┘ ┴ └┘└┘└───────┘└──┘ └────┘└───────────────────┘
doc └────┘ └┘ └──┘ └───────────────────┘
txt └────┘ └┘ └──┘ └───────────────────┘
par └────┘ └┘ └──┘ └───────────────────┘
pid ┴ └┘ └──┘ └──────────────────┘┴
st ─────┘└─────────────────────────────────────────────────────┘└┘└
190 { exact ⟨y::l₁, perm.refl _, (s.cons2 _ _ _).cons _ _ _⟩ },
id ┴ └┘ └───────┘ └─────┘
src └────┘ └┘└───────┘└──┘ └─────┘└──────────────────┘
typ └────┘ ┴ └┘└┘└───────┘└──┘ └─────┘└──────────────────┘
doc └────┘ └┘ └──┘ └──────────────────┘
txt └────┘ └┘ └──┘ └──────────────────┘
par └────┘ └┘ └──┘ └──────────────────┘
pid ┴ └┘ └──┘ └─────────────────┘┴
st ─────┘└─────────────────────────────────────────────────────┘└┘└
191 { exact ⟨x::y::l₁, perm.swap _ _ _, (s.cons2 _ _ _).cons2 _ _ _⟩ } },
id ┴ ┴ └┘ └───────┘ └─────┘
src └────┘ └┘└───────┘└──────┘ └─────┘└───────────────────┘
typ └────┘ ┴ ┴ └┘└┘└───────┘└──────┘ └─────┘└───────────────────┘
doc └────┘ └┘ └──────┘ └───────────────────┘
txt └────┘ └┘ └──────┘ └───────────────────┘
par └────┘ └┘ └──────┘ └───────────────────┘
pid ┴ └┘ └──────┘ └──────────────────┘┴
st ────────────────────────────────────────────────────────────────────┘└──┘└
192 { exact let ⟨m₁, pm, sm⟩ := IH₁ s, ⟨r₁, pr, sr⟩ := IH₂ sm in
id └┘ └┘ └─┘ ┴ └┘ └┘ └┘ └─┘
src └────┘ ┴ └┘ └┘ └───┘ ┴ └┘ └┘ └┘ └───┘ ┴ └───
typ └────┘ ┴ └┘└┘└┘└┘└───┘└─┘┴┴└┘ └┘└┘└┘└┘└┘└───┘└─┘┴ └───
doc └────┘ ┴ └┘ └┘ └───┘ ┴ └┘ └┘ └┘ └───┘ ┴ └───
txt └────┘ ┴ └┘ └┘ └───┘ ┴ └┘ └┘ └┘ └───┘ ┴ └───
par └────┘ ┴ └┘ └┘ └───┘ ┴ └┘ └┘ └┘ └───┘ ┴ └───
pid ┴ ┴ └┘ └┘ └───┘ ┴ └┘ └┘ └┘ └───┘ ┴ └───
st ───────────────────────────────────────────────────────────────
193 ⟨r₁, pr.trans pm, sr⟩ }
id └────┘
src ─────────┘ └┘ └────┘┴ └┘ └┘
typ ─────────┘ └┘ └────┘┴ └┘ └┘
doc ─────────┘ └┘ ┴ └┘ └┘
txt ─────────┘ └┘ ┴ └┘ └┘
par ─────────┘ └┘ ┴ └┘ └┘
pid ─────────┘ └┘ ┴ └┘ ┴┴
st ───────────────────────────────┘└─
194 end
st ──┘
195
196 section rel
197 open relator
198 variables {γ : Type*} {δ : Type*} {r : α → β → Prop} {p : γ → δ → Prop}
199
200 local infixr ` ∘r ` : 80 := relation.comp
id └───────────┘
src └───────────┘
typ └───────────┘
201
202 lemma perm_comp_perm : (perm ∘r perm : list α → list α → Prop) = perm :=
id └──┘ └┘ └──┘ └──┘ ┴ └──┘ ┴ ┴ └──┘
src └──┘ └┘ └──┘ └──┘ └──┘ ┴ └──┘
typ └──┘ └┘ └──┘ └──┘ ┴ └──┘ ┴ ┴ └──┘
doc └──┘ └──┘ └──┘
203 begin
st └─────
204 funext a c, apply propext,
id └─────┘
src └────────┘ └────┘└─────┘
typ └────────┘ └────┘└─────┘
doc └────────┘ └────┘
txt └────────┘ └────┘
par └────────┘ └────┘
pid └──┘ ┴
st ───────────┘└─────────────┘└─
205 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ──────┘└─
206 { exact assume ⟨b, hab, hba⟩, perm.trans hab hba },
id └─┘ └─┘ └────────┘
src └────┘ └┘ └┘ └┘ └─┘└────────┘┴ ┴ ┴
typ └────┘ └┘ └┘└─┘└┘└─┘└─┘└────────┘┴ ┴ ┴
doc └────┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
txt └────┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
par └────┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
pid ┴ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
st ───┘└─────────────────────────────────────────────┘└┘└
207 { exact assume h, ⟨a, perm.refl a, h⟩ }
id └───────┘ ┴
src └────┘ └──┘ └┘└───────┘┴ └┘ └┘
typ └────┘ └──┘ └┘└───────┘┴┴└┘ └┘
doc └────┘ └──┘ └┘ ┴ └┘ └┘
txt └────┘ └──┘ └┘ ┴ └┘ └┘
par └────┘ └──┘ └┘ ┴ └┘ └┘
pid ┴ └──┘ └┘ ┴ └┘ ┴┴
st ───────────────────────────────────────┘└─
208 end
st ──┘
209
210 lemma perm_comp_forall₂ {l u v} (hlu : perm l u) (huv : forall₂ r u v) : (forall₂ r ∘r perm) l v :=
id └──┘ ┴ ┴ └─────┘ ┴ ┴ ┴ └─────┘ ┴ └┘ └──┘ ┴ ┴
src └──┘ └─────┘ └─────┘ └┘ └──┘
typ └──┘ ┴ ┴ └─────┘ ┴ ┴ ┴ └─────┘ ┴ └┘ └──┘ ┴ ┴
doc └──┘ └──┘
211 begin
st └─────
212 induction hlu generalizing v,
id └─┘
src └────────┘ └─────────────┘
typ └────────┘└─┘└─────────────┘
doc └────────┘ └─────────────┘
txt └────────┘ └─────────────┘
par └────────┘ └─────────────┘
pid ┴ ┴└────────────┘
st ─────────────────────────────┘└─
213 case perm.nil { cases huv, exact ⟨[], forall₂.nil, perm.nil⟩ },
id └─┘ └─────────┘ └──────┘
src └──────────────┘└────┘ └┘└────┘ └┘└─────────┘└┘└──────┘└┘┴
typ └──────────────┘└────┘└─┘└┘└────┘ └┘└─────────┘└┘└──────┘└┘┴
doc └──────────────┘└────┘ └┘└────┘ └┘ └┘ └┘┴
txt └──────────────┘└────┘ └┘└────┘ └┘ └┘ └┘┴
par └──────────────┘└────┘ └┘└────┘ └┘ └┘ └┘┴
pid └───────┘┴└──────┘ └──────┘ └┘ └┘ └─┘
st ────────────────┘└────────┘└──────────────────────────────────┘└┘└
214 case perm.skip : a l u hlu ih {
src └───────────────────────────────
typ └───────────────────────────────
doc └───────────────────────────────
txt └───────────────────────────────
par └───────────────────────────────
pid └────────┘└─────────────┘└──
st ────────────────────────────────┘└
215 cases huv with _ b _ v hab huv',
id └─┘
src ───┘└────┘ └────────────────────┘└─
typ ───┘└────┘└─┘└────────────────────┘└─
doc ───┘└────┘ └────────────────────┘└─
txt ───┘└────┘ └────────────────────┘└─
par ───┘└────┘ └────────────────────┘└─
pid ─────────┘ └───────────────────────
st ──────────────────────────────────┘└─
216 rcases ih huv' with ⟨l₂, h₁₂, h₂₃⟩,
id └┘ └──┘
src ───┘└─────┘ ┴ └──────────────────┘└─
typ ───┘└─────┘└┘┴└──┘└──────────────────┘└─
doc ───┘└─────┘ ┴ └──────────────────┘└─
txt ───┘└─────┘ ┴ └──────────────────┘└─
par ───┘└─────┘ ┴ └──────────────────┘└─
pid ──────────┘ ┴ └─────────────────────
st ─────────────────────────────────────┘└─
217 exact ⟨b::l₂, forall₂.cons hab h₁₂, perm.skip _ h₂₃⟩
id ┴ └┘ └──────────┘ └─┘ └─┘ └───────┘ └─┘
src ───┘└────┘ └┘└──────────┘┴ ┴ └┘└───────┘└─┘ └─
typ ───┘└────┘ ┴ └┘└┘└──────────┘┴└─┘┴└─┘└┘└───────┘└─┘└─┘└─
doc ───┘└────┘ └┘ ┴ ┴ └┘ └─┘ └─
txt ───┘└────┘ └┘ ┴ ┴ └┘ └─┘ └─
par ───┘└────┘ └┘ ┴ ┴ └┘ └─┘ └─
pid ─────────┘ └┘ ┴ ┴ └┘ └─┘ └─
st ─────────────────────────────────────────────────────────
218 },
src ─┘┴
typ ─┘┴
doc ─┘┴
txt ─┘┴
par ─┘┴
pid ──┘
st ─┘└┘└
219 case perm.swap : a₁ a₂ l₁ l₂ h₂₃ {
src └──────────────────────────────────
typ └──────────────────────────────────
doc └──────────────────────────────────
txt └──────────────────────────────────
par └──────────────────────────────────
pid └────────┘└────────────────┘└──
st ───────────────────────────────────┘└
220 cases h₂₃ with _ b₁ _ l₂ h₁ hr_₂₃,
id └─┘
src ───┘└────┘ └──────────────────────┘└─
typ ───┘└────┘└─┘└──────────────────────┘└─
doc ───┘└────┘ └──────────────────────┘└─
txt ───┘└────┘ └──────────────────────┘└─
par ───┘└────┘ └──────────────────────┘└─
pid ─────────┘ └─────────────────────────
st ────────────────────────────────────┘└─
221 cases hr_₂₃ with _ b₂ _ l₂ h₂ h₁₂,
id └───┘
src ───┘└────┘ └────────────────────┘└─
typ ───┘└────┘└───┘└────────────────────┘└─
doc ───┘└────┘ └────────────────────┘└─
txt ───┘└────┘ └────────────────────┘└─
par ───┘└────┘ └────────────────────┘└─
pid ─────────┘ └───────────────────────
st ────────────────────────────────────┘└─
222 exact ⟨b₂::b₁::l₂, forall₂.cons h₂ (forall₂.cons h₁ h₁₂), perm.swap _ _ _⟩
id └┘ └┘ └┘ └┘ └──────────┘ └┘ └─┘ └───────┘
src ───┘└────┘ └┘ ┴ ┴ └──────────┘┴ ┴ └─┘└───────┘└───────
typ ───┘└────┘ └┘ └┘ └┘└┘ ┴└┘┴ └──────────┘┴└┘┴└─┘└─┘└───────┘└───────
doc ───┘└────┘ └┘ ┴ ┴ ┴ ┴ └─┘ └───────
txt ───┘└────┘ └┘ ┴ ┴ ┴ ┴ └─┘ └───────
par ───┘└────┘ └┘ ┴ ┴ ┴ ┴ └─┘ └───────
pid ─────────┘ └┘ ┴ ┴ ┴ ┴ └─┘ └───────
st ───────────────────────────────────────────────────────────────────────────────
223 },
src ─┘┴
typ ─┘┴
doc ─┘┴
txt ─┘┴
par ─┘┴
pid ──┘
st ─┘└┘└
224 case perm.trans : la₁ la₂ la₃ _ _ ih₁ ih₂ {
src └───────────────────────────────────────────
typ └───────────────────────────────────────────
doc └───────────────────────────────────────────
txt └───────────────────────────────────────────
par └───────────────────────────────────────────
pid └─────────┘└────────────────────────┘└──
st ────────────────────────────────────────────┘└
225 rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩,
id └─┘ └─┘
src ───┘└─────┘ ┴ └────────────────────┘└─
typ ───┘└─────┘└─┘┴└─┘└────────────────────┘└─
doc ───┘└─────┘ ┴ └────────────────────┘└─
txt ───┘└─────┘ ┴ └────────────────────┘└─
par ───┘└─────┘ ┴ └────────────────────┘└─
pid ──────────┘ ┴ └───────────────────────
st ───────────────────────────────────────┘└─
226 rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩,
id └─┘ └──┘
src ───┘└─────┘ ┴ └────────────────────┘└─
typ ───┘└─────┘└─┘┴└──┘└────────────────────┘└─
doc ───┘└─────┘ ┴ └────────────────────┘└─
txt ───┘└─────┘ ┴ └────────────────────┘└─
par ───┘└─────┘ ┴ └────────────────────┘└─
pid ──────────┘ ┴ └───────────────────────
st ────────────────────────────────────────┘└─
227 exact ⟨lb₁, hab₁, perm.trans h₁₂ h₂₃⟩
id └─┘ └──┘ └────────┘ └─┘ └─┘
src ───┘└────┘ └┘ └┘└────────┘┴ ┴ └─
typ ───┘└────┘ └─┘└┘└──┘└┘└────────┘┴└─┘┴└─┘└─
doc ───┘└────┘ └┘ └┘ ┴ ┴ └─
txt ───┘└────┘ └┘ └┘ ┴ ┴ └─
par ───┘└────┘ └┘ └┘ ┴ ┴ └─
pid ─────────┘ └┘ └┘ ┴ ┴ └─
st ──────────────────────────────────────────
228 }
src ─┘└┘
typ ─┘└┘
doc ─┘└┘
txt ─┘└┘
par ─┘└┘
pid ──┘┴
st ─┘┴┴
229 end
st └─┘
230
231 lemma forall₂_comp_perm_eq_perm_comp_forall₂ : forall₂ r ∘r perm = perm ∘r forall₂ r :=
id └─────┘ ┴ └┘ └──┘ ┴ └──┘ └┘ └─────┘ ┴
src └─────┘ └┘ └──┘ ┴ └──┘ └┘ └─────┘
typ └─────┘ ┴ └┘ └──┘ ┴ └──┘ └┘ └─────┘ ┴
doc └──┘ └──┘
232 begin
st └─────
233 funext l₁ l₃, apply propext,
id └─────┘
src └──────────┘ └────┘└─────┘
typ └──────────┘ └────┘└─────┘
doc └──────────┘ └────┘
txt └──────────┘ └────┘
par └──────────┘ └────┘
pid └────┘ ┴
st ─────────────┘└─────────────┘└─
234 split,
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
st ──────┘└─
235 { assume h, rcases h with ⟨l₂, h₁₂, h₂₃⟩,
id ┴
src └──────┘ └─────┘ └──────────────────┘
typ └──────┘ └─────┘┴└──────────────────┘
doc └──────┘ └─────┘ └──────────────────┘
txt └──────┘ └─────┘ └──────────────────┘
par └──────┘ └─────┘ └──────────────────┘
pid └──────┘ ┴ └──────────────────┘
st ───┘└──────┘└────────────────────────────┘└─
236 have : forall₂ (flip r) l₂ l₁, from h₁₂.flip ,
id └─────┘ └──┘ ┴ └┘ └┘ └──────┘
src └─────┘└─────┘┴ └──┘┴ └┘ ┴ └───┘└──────┘┴
typ └─────┘└─────┘┴ └──┘┴┴└┘└┘┴└┘ └───┘└──────┘┴
doc └─────┘ ┴ ┴ └┘ ┴ └───┘ ┴
txt └─────┘ ┴ ┴ └┘ ┴ └───┘ ┴
par └─────┘ ┴ ┴ └┘ ┴ └───┘ ┴
pid └───┘└┘ ┴ ┴ └┘ ┴ └───┘ ┴
st ────────────────────────────────┘└──────────────┘└─
237 rcases perm_comp_forall₂ h₂₃.symm this with ⟨l', h₁, h₂⟩,
id └───────────────┘ └──────┘ └──┘
src └─────┘└───────────────┘┴└──────┘┴ └────────────────┘
typ └─────┘└───────────────┘┴└──────┘┴└──┘└────────────────┘
doc └─────┘ ┴ ┴ └────────────────┘
txt └─────┘ ┴ ┴ └────────────────┘
par └─────┘ ┴ ┴ └────────────────┘
pid ┴ ┴ ┴ └────────────────┘
st ───────────────────────────────────────────────────────────┘└─
238 exact ⟨l', h₂.symm, h₁.flip⟩ },
id └┘ └─────┘ └─────┘
src └────┘ └┘└─────┘└┘└─────┘└┘
typ └────┘ └┘└┘└─────┘└┘└─────┘└┘
doc └────┘ └┘ └┘ └┘
txt └────┘ └┘ └┘ └┘
par └────┘ └┘ └┘ └┘
pid ┴ └┘ └┘ ┴┴
st ────────────────────────────────┘└┘└
239 { exact assume ⟨l₂, h₁₂, h₂₃⟩, perm_comp_forall₂ h₁₂ h₂₃ }
id └─┘ └─┘ └───────────────┘
src └────┘ └┘ └┘ └┘ └─┘└───────────────┘┴ ┴ ┴
typ └────┘ └┘ └┘└─┘└┘└─┘└─┘└───────────────┘┴ ┴ ┴
doc └────┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
txt └────┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
par └────┘ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
pid ┴ └┘ └┘ └┘ └─┘ ┴ ┴ ┴
st ──────────────────────────────────────────────────────────┘└─
240 end
st ──┘
241
242 lemma rel_perm_imp (hr : right_unique r) : (forall₂ r ⇒ forall₂ r ⇒ implies) perm perm :=
id └──────────┘ ┴ └─────┘ ┴ ┴ └─────┘ ┴ ┴ └─────┘ └──┘ └──┘
src └──────────┘ └─────┘ ┴ └─────┘ ┴ └─────┘ └──┘ └──┘
typ └──────────┘ ┴ └─────┘ ┴ ┴ └─────┘ ┴ ┴ └─────┘ └──┘ └──┘
doc └──┘ └──┘
243 assume a b h₁ c d h₂ h,
id ┴ ┴ └┘ ┴ ┴ └┘ ┴
typ ┴ ┴ └┘ ┴ ┴ └┘ ┴
244 have (flip (forall₂ r) ∘r (perm ∘r forall₂ r)) b d, from ⟨a, h₁, c, h, h₂⟩,
id └──┘ └─────┘ ┴ └┘ └──┘ └┘ └─────┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘
src └──┘ └─────┘ └┘ └──┘ └┘ └─────┘
typ └──┘ └─────┘ ┴ └┘ └──┘ └┘ └─────┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘
doc └──┘
245 have ((flip (forall₂ r) ∘r forall₂ r) ∘r perm) b d,
id └──┘ └─────┘ ┴ └┘ └─────┘ ┴ └┘ └──┘ ┴ ┴
src └──┘ └─────┘ └┘ └─────┘ └┘ └──┘
typ └──┘ └─────┘ ┴ └┘ └─────┘ ┴ └┘ └──┘ ┴ ┴
doc └──┘
246 by rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← relation.comp_assoc] at this,
id └────────────────────────────────────┘ └─────────────────┘
src └─────┘└────────────────────────────────────┘└──┘└─────────────────┘└───────┘
typ └─────┘└────────────────────────────────────┘└──┘└─────────────────┘└───────┘
doc └─────┘ └──┘ └───────┘
txt └─────┘ └──┘ └───────┘
par └─────┘ └──┘ └───────┘
pid └──┘ └──┘ ┴└──────┘
st └────────────────────────────────────────────┘└─────────────────────┘┴└──────┘
247 let ⟨b', ⟨c', hbc, hcb⟩, hbd⟩ := this in
id └─┘ └┘ └─┘ └─┘ └─┘ └──┘
typ └─┘ └┘ └─┘ └─┘ └─┘ └──┘
248 have b' = b, from right_unique_forall₂ @hr hcb hbc,
id ┴ ┴ └──────────────────┘ └┘
src ┴ └──────────────────┘
typ ┴ ┴ └──────────────────┘ └┘
249 this ▸ hbd
id └──┘ ┴
src ┴
typ └──┘ ┴
250
251 lemma rel_perm (hr : bi_unique r) : (forall₂ r ⇒ forall₂ r ⇒ (↔)) perm perm :=
id └───────┘ ┴ └─────┘ ┴ ┴ └─────┘ ┴ ┴ ┴ └──┘ └──┘
src └───────┘ └─────┘ ┴ └─────┘ ┴ ┴ └──┘ └──┘
typ └───────┘ ┴ └─────┘ ┴ ┴ └─────┘ ┴ ┴ ┴ └──┘ └──┘
doc └──┘ └──┘
252 assume a b hab c d hcd, iff.intro
id ┴ ┴ └─┘ ┴ ┴ └─┘ └───────┘
src └───────┘
typ ┴ ┴ └─┘ ┴ ┴ └─┘ └───────┘
253 (rel_perm_imp hr.2 hab hcd)
id └──────────┘ └┘┴ └─┘ └─┘
src └──────────┘ ┴
typ └──────────┘ └┘┴ └─┘ └─┘
254 (rel_perm_imp (assume a b c, left_unique_flip hr.1) hab.flip hcd.flip)
id └──────────┘ ┴ ┴ ┴ └──────────────┘ └┘┴ └─┘└───┘ └─┘└───┘
src └──────────┘ └──────────────┘ ┴ └───┘ └───┘
typ └──────────┘ ┴ ┴ ┴ └──────────────┘ └┘┴ └─┘└───┘ └─┘└───┘
255
256 end rel
257
258 section subperm
259
260 /-- `subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
261 a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
262 multiplicities of elements, and is used for the `≤` relation on multisets. -/
263 def subperm (l₁ l₂ : list α) : Prop := ∃ l ~ l₁, l <+ l₂
id └──┘ ┴ ┴ ┴ └┘┴ ┴ └┘ └┘
src └──┘ ┴ ┴ └┘
typ └──┘ ┴ ┴ ┴ └┘┴ ┴ └┘ └┘
264
265 infix ` <+~ `:50 := subperm
id └─────┘
src └─────┘
typ └─────┘
doc └─────┘
266
267 theorem nil_subperm {l : list α} : [] <+~ l :=
id └──┘ ┴ └┘ └─┘ ┴
src └──┘ └┘ └─┘
typ └──┘ ┴ └┘ └─┘ ┴
doc └─┘
268 ⟨[], perm.nil, by simp⟩
id └┘ └──────┘
src └┘ └──────┘ └──┘
typ └┘ └──────┘ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
269
270 theorem perm.subperm_left {l l₁ l₂ : list α} (p : l₁ ~ l₂) : l <+~ l₁ ↔ l <+~ l₂ :=
id └──┘ ┴ └┘ ┴ └┘ ┴ └─┘ └┘ ┴ ┴ └─┘ └┘
src └──┘ ┴ └─┘ ┴ └─┘
typ └──┘ ┴ └┘ ┴ └┘ ┴ └─┘ └┘ ┴ ┴ └─┘ └┘
doc ┴ └─┘ └─┘
271 suffices ∀ {l₁ l₂ : list α}, l₁ ~ l₂ → l <+~ l₁ → l <+~ l₂,
id └──┘ ┴ └┘ ┴ └┘ ┴ └─┘ └┘ ┴ └─┘ └┘
src └──┘ ┴ └─┘ └─┘
typ └──┘ ┴ └┘ ┴ └┘ ┴ └─┘ └┘ ┴ └─┘ └┘
doc ┴ └─┘ └─┘
272 from ⟨this p, this p.symm⟩,
id └──┘ ┴ └──┘ ┴└───┘
src └───┘
typ └──┘ ┴ └──┘ ┴└───┘
273 λ l₁ l₂ p ⟨u, pu, su⟩,
id └┘ └┘ ┴ ┴ └┘ └┘
typ └┘ └┘ ┴ ┴ └┘ └┘
274 let ⟨v, pv, sv⟩ := exists_perm_sublist su p in
id └─┘ ┴ └┘ └┘ └─────────────────┘ ┴
src └─────────────────┘
typ └─┘ ┴ └┘ └┘ └─────────────────┘ ┴
275 ⟨v, pv.trans pu, sv⟩
id └────┘
src └────┘
typ └────┘
276
277 theorem perm.subperm_right {l₁ l₂ l : list α} (p : l₁ ~ l₂) : l₁ <+~ l ↔ l₂ <+~ l :=
id └──┘ ┴ └┘ ┴ └┘ └┘ └─┘ ┴ ┴ └┘ └─┘ ┴
src └──┘ ┴ └─┘ ┴ └─┘
typ └──┘ ┴ └┘ ┴ └┘ └┘ └─┘ ┴ ┴ └┘ └─┘ ┴
doc ┴ └─┘ └─┘
278 ⟨λ ⟨u, pu, su⟩, ⟨u, pu.trans p, su⟩,
id ┴┴ └┘ └┘ └────┘ ┴
src └────┘
typ ┴┴ └┘ └┘ └────┘ ┴
279 λ ⟨u, pu, su⟩, ⟨u, pu.trans p.symm, su⟩⟩
id ┴┴ └┘ └┘ └────┘ ┴└───┘
src └────┘ └───┘
typ ┴┴ └┘ └┘ └────┘ ┴└───┘
280
281 theorem subperm_of_sublist {l₁ l₂ : list α} (s : l₁ <+ l₂) : l₁ <+~ l₂ :=
id └──┘ ┴ └┘ └┘ └┘ └┘ └─┘ └┘
src └──┘ └┘ └─┘
typ └──┘ ┴ └┘ └┘ └┘ └┘ └─┘ └┘
doc └─┘
282 ⟨l₁, perm.refl _, s⟩
id └┘ └───────┘ ┴
src └───────┘
typ └┘ └───────┘ ┴
283
284 theorem subperm_of_perm {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₁ <+~ l₂ :=
id └──┘ ┴ └┘ ┴ └┘ └┘ └─┘ └┘
src └──┘ ┴ └─┘
typ └──┘ ┴ └┘ ┴ └┘ └┘ └─┘ └┘
doc ┴ └─┘
285 ⟨l₂, p.symm, sublist.refl _⟩
id └┘ ┴└───┘ └──────────┘
src └───┘ └──────────┘
typ └┘ ┴└───┘ └──────────┘
286
287 theorem subperm.refl (l : list α) : l <+~ l := subperm_of_perm (perm.refl _)
id └──┘ ┴ ┴ └─┘ ┴ └─────────────┘ └───────┘
src └──┘ └─┘ └─────────────┘ └───────┘
typ └──┘ ┴ ┴ └─┘ ┴ └─────────────┘ └───────┘
doc └─┘
288
289 theorem subperm.trans {l₁ l₂ l₃ : list α} : l₁ <+~ l₂ → l₂ <+~ l₃ → l₁ <+~ l₃
id └──┘ ┴ └┘ └─┘ └┘ ┴ └┘ └─┘ └┘ └┘ └─┘ └┘
src └──┘ └─┘ └─┘ └─┘
typ └──┘ ┴ └┘ └─┘ └┘ ┴ └┘ └─┘ └┘ └┘ └─┘ └┘
doc └─┘ └─┘ └─┘
290 | s ⟨l₂', p₂, s₂⟩ :=
id ┴ └┘ └┘
typ ┴ └┘ └┘
291 let ⟨l₁', p₁, s₁⟩ := p₂.subperm_left.2 s in ⟨l₁', p₁, s₁.trans s₂⟩
id └─┘ └─┘ └┘ └┘ └───────────┘┴ └────┘
src └───────────┘┴ └────┘
typ └─┘ └─┘ └┘ └┘ └───────────┘┴ └────┘
292
293 theorem length_le_of_subperm {l₁ l₂ : list α} : l₁ <+~ l₂ → length l₁ ≤ length l₂
id └──┘ ┴ └┘ └─┘ └┘ ┴ └────┘ └┘ ┴ └────┘ └┘
src └──┘ └─┘ └────┘ ┴ └────┘
typ └──┘ ┴ └┘ └─┘ └┘ ┴ └────┘ └┘ ┴ └────┘ └┘
doc └─┘
294 | ⟨l, p, s⟩ := perm_length p ▸ length_le_of_sublist s
id ┴ ┴ └─────────┘ ┴ └──────────────────┘
src └─────────┘ ┴ └──────────────────┘
typ ┴ ┴ └─────────┘ ┴ └──────────────────┘
295
296 theorem subperm.perm_of_length_le {l₁ l₂ : list α} : l₁ <+~ l₂ → length l₂ ≤ length l₁ → l₁ ~ l₂
id └──┘ ┴ └┘ └─┘ └┘ ┴ └────┘ └┘ ┴ └────┘ └┘ └┘ ┴ └┘
src └──┘ └─┘ └────┘ ┴ └────┘ ┴
typ └──┘ ┴ └┘ └─┘ └┘ ┴ └────┘ └┘ ┴ └────┘ └┘ └┘ ┴ └┘
doc └─┘ ┴
297 | ⟨l, p, s⟩ h :=
id ┴ ┴ ┴ ┴
typ ┴ ┴ ┴ ┴
298 suffices l = l₂, from this ▸ p.symm,
id ┴ └┘ └──┘ ┴ └───┘
src ┴ ┴ └───┘
typ ┴ └┘ └──┘ ┴ └───┘
299 eq_of_sublist_of_length_le s $ perm_length p.symm ▸ h
id └────────────────────────┘ └─────────┘ └───┘ ┴
src └────────────────────────┘ └─────────┘ └───┘ ┴
typ └────────────────────────┘ └─────────┘ └───┘ ┴
300
301 theorem subperm.antisymm {l₁ l₂ : list α} (h₁ : l₁ <+~ l₂) (h₂ : l₂ <+~ l₁) : l₁ ~ l₂ :=
id └──┘ ┴ └┘ └─┘ └┘ └┘ └─┘ └┘ └┘ ┴ └┘
src └──┘ └─┘ └─┘ ┴
typ └──┘ ┴ └┘ └─┘ └┘ └┘ └─┘ └┘ └┘ ┴ └┘
doc └─┘ └─┘ ┴
302 h₁.perm_of_length_le (length_le_of_subperm h₂)
id └┘└────────────────┘ └──────────────────┘ └┘
src └────────────────┘ └──────────────────┘
typ └┘└────────────────┘ └──────────────────┘ └┘
303
304 theorem subset_of_subperm {l₁ l₂ : list α} : l₁ <+~ l₂ → l₁ ⊆ l₂
id └──┘ ┴ └┘ └─┘ └┘ ┴ └┘ ┴ └┘
src └──┘ └─┘ ┴
typ └──┘ ┴ └┘ └─┘ └┘ ┴ └┘ ┴ └┘
doc └─┘
305 | ⟨l, p, s⟩ := subset.trans (perm_subset p.symm) (subset_of_sublist s)
id ┴ ┴ └──────────┘ └─────────┘ └───┘ └───────────────┘
src └──────────┘ └─────────┘ └───┘ └───────────────┘
typ ┴ ┴ └──────────┘ └─────────┘ └───┘ └───────────────┘
306
307 end subperm
308
309 theorem exists_perm_append_of_sublist : ∀ {l₁ l₂ : list α}, l₁ <+ l₂ → ∃ l, l₂ ~ l₁ ++ l
id ┴ └──┘ ┴ └┘ └┘ └┘ ┴ ┴┴ └┘ ┴ └┘ └┘ ┴
src └──┘ └┘ ┴ ┴ ┴ └┘
typ ┴ └──┘ ┴ └┘ └┘ └┘ ┴ ┴┴ └┘ ┴ └┘ └┘ ┴
doc ┴
310 | ._ ._ sublist.slnil := ⟨nil, perm.refl _⟩
id └───────────┘ └─┘ └───────┘
src └───────────┘ └─┘ └───────┘
typ └───────────┘ └─┘ └───────┘
311 | ._ ._ (sublist.cons l₁ l₂ a s) :=
id └──────────┘ ┴ ┴
src └──────────┘
typ └──────────┘ ┴ ┴
312 let ⟨l, p⟩ := exists_perm_append_of_sublist s in
id └─┘ ┴ ┴ └───────────────────────────┘
typ └─┘ ┴ ┴ └───────────────────────────┘
313 ⟨a::l, (skip a p).trans perm_middle.symm⟩
id └┘ └──┘ └───┘ └─────────┘└───┘
src └┘ └──┘ └───┘ └─────────┘└───┘
typ └┘ └──┘ └───┘ └─────────┘└───┘
314 | ._ ._ (sublist.cons2 l₁ l₂ a s) :=
id └───────────┘ ┴ ┴
src └───────────┘
typ └───────────┘ ┴ ┴
315 let ⟨l, p⟩ := exists_perm_append_of_sublist s in
id └─┘ ┴ ┴ └───────────────────────────┘
typ └─┘ ┴ ┴ └───────────────────────────┘
316 ⟨l, skip a p⟩
id └──┘
src └──┘
typ └──┘
317
318 theorem perm_countp (p : α → Prop) [decidable_pred p]
id ┴ └────────────┘ ┴
src └────────────┘
typ ┴ └────────────┘ ┴
319 {l₁ l₂ : list α} (s : l₁ ~ l₂) : countp p l₁ = countp p l₂ :=
id └──┘ ┴ └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
src └──┘ ┴ └────┘ ┴ └────┘
typ └──┘ ┴ └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
doc ┴ └────┘ └────┘
320 by rw [countp_eq_length_filter, countp_eq_length_filter];
id └─────────────────────┘ └─────────────────────┘
src └──┘└─────────────────────┘└┘└─────────────────────┘┴
typ └──┘└─────────────────────┘└┘└─────────────────────┘┴
doc └──┘ └┘ ┴
txt └──┘ └┘ ┴
par └──┘ └┘ ┴
pid └┘ └┘ ┴
st └──────────────────────────┘└───────────────────────┘┴└─
321 exact perm_length (perm_filter _ s)
id └─────────┘ └─────────┘ ┴
src └────┘└─────────┘┴ └─────────┘└─┘ └─
typ └────┘└─────────┘┴ └─────────┘└─┘┴└─
doc └────┘ ┴ └─┘ └─
txt └────┘ ┴ └─┘ └─
par └────┘ ┴ └─┘ └─
pid ┴ ┴ └─┘ ┴└
st ───────────────────────────────────────
322
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
323 theorem countp_le_of_subperm (p : α → Prop) [decidable_pred p]
id ┴ └────────────┘ ┴
src └────────────┘
typ ┴ └────────────┘ ┴
324 {l₁ l₂ : list α} : l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
id └──┘ ┴ └┘ └─┘ └┘ ┴ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
src └──┘ └─┘ └────┘ ┴ └────┘
typ └──┘ ┴ └┘ └─┘ └┘ ┴ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
doc └─┘ └────┘ └────┘
325 | ⟨l, p', s⟩ := perm_countp p p' ▸ countp_le_of_sublist s
id └┘ ┴ └─────────┘ ┴ ┴ └──────────────────┘
src └─────────┘ ┴ └──────────────────┘
typ └┘ ┴ └─────────┘ ┴ ┴ └──────────────────┘
326
327 theorem perm_count [decidable_eq α] {l₁ l₂ : list α}
id └──────────┘ ┴ └──┘ ┴
src └──────────┘ └──┘
typ └──────────┘ ┴ └──┘ ┴
328 (p : l₁ ~ l₂) (a) : count a l₁ = count a l₂ :=
id └┘ ┴ └┘ └───┘ ┴ └┘ ┴ └───┘ ┴ └┘
src ┴ └───┘ ┴ └───┘
typ └┘ ┴ └┘ └───┘ ┴ └┘ ┴ └───┘ ┴ └┘
doc ┴ └───┘ └───┘
329 perm_countp _ p
id └─────────┘ ┴
src └─────────┘
typ └─────────┘ ┴
330
331 theorem count_le_of_subperm [decidable_eq α] {l₁ l₂ : list α}
id └──────────┘ ┴ └──┘ ┴
src └──────────┘ └──┘
typ └──────────┘ ┴ └──┘ ┴
332 (s : l₁ <+~ l₂) (a) : count a l₁ ≤ count a l₂ :=
id └┘ └─┘ └┘ └───┘ ┴ └┘ ┴ └───┘ ┴ └┘
src └─┘ └───┘ ┴ └───┘
typ └┘ └─┘ └┘ └───┘ ┴ └┘ ┴ └───┘ ┴ └┘
doc └─┘ └───┘ └───┘
333 countp_le_of_subperm _ s
id └──────────────────┘ ┴
src └──────────────────┘
typ └──────────────────┘ ┴
334
335 theorem foldl_eq_of_perm {f : β → α → β} {l₁ l₂ : list α} (rcomm : right_commutative f) (p : l₁ ~ l₂) :
id ┴ ┴ ┴ └──┘ ┴ └───────────────┘ ┴ └┘ ┴ └┘
src └──┘ └───────────────┘ ┴
typ ┴ ┴ ┴ └──┘ ┴ └───────────────┘ ┴ └┘ ┴ └┘
doc ┴
336 ∀ b, foldl f b l₁ = foldl f b l₂ :=
id ┴ └───┘ ┴ ┴ └┘ ┴ └───┘ ┴ ┴ └┘
src └───┘ ┴ └───┘
typ ┴ └───┘ ┴ ┴ └┘ ┴ └───┘ ┴ ┴ └┘
337 perm_induction_on p
id └───────────────┘ ┴
src └───────────────┘
typ └───────────────┘ ┴
338 (λ b, rfl)
id ┴ └─┘
src └─┘
typ ┴ └─┘
339 (λ x t₁ t₂ p r b, r (f b x))
id ┴ └┘ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
typ ┴ └┘ └┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
340 (λ x y t₁ t₂ p r b, by simp; rw rcomm; exact r (f (f b x) y))
id ┴ ┴ └┘ └┘ ┴ ┴ ┴ └───┘ ┴ ┴ ┴ ┴ ┴
src └──┘ └─┘ └────┘ ┴ ┴ ┴ ┴ └┘ ┴
typ ┴ ┴ └┘ └┘ ┴ ┴ ┴ └──┘ └─┘└───┘ └────┘┴┴ ┴ ┴┴┴┴┴└┘┴┴
doc └──┘ └─┘ └────┘ ┴ ┴ ┴ ┴ └┘ ┴
txt └──┘ └─┘ └────┘ ┴ ┴ ┴ ┴ └┘ ┴
par └──┘ └─┘ └────┘ ┴ ┴ ┴ ┴ └┘ ┴
pid ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴
st └────────┘└───┘└─────────────────────┘
341 (λ t₁ t₂ t₃ p₁ p₂ r₁ r₂ b, eq.trans (r₁ b) (r₂ b))
id └┘ └┘ └┘ └┘ └┘ └┘ └┘ ┴ └──────┘ └┘ ┴ └┘ ┴
src └──────┘
typ └┘ └┘ └┘ └┘ └┘ └┘ └┘ ┴ └──────┘ └┘ ┴ └┘ ┴
342
343 theorem foldr_eq_of_perm {f : α → β → β} {l₁ l₂ : list α} (lcomm : left_commutative f) (p : l₁ ~ l₂) :
id ┴ ┴ ┴ └──┘ ┴ └──────────────┘ ┴ └┘ ┴ └┘
src └──┘ └──────────────┘ ┴
typ ┴ ┴ ┴ └──┘ ┴ └──────────────┘ ┴ └┘ ┴ └┘
doc ┴
344 ∀ b, foldr f b l₁ = foldr f b l₂ :=
id ┴ └───┘ ┴ ┴ └┘ ┴ └───┘ ┴ ┴ └┘
src └───┘ ┴ └───┘
typ ┴ └───┘ ┴ ┴ └┘ ┴ └───┘ ┴ ┴ └┘
345 perm_induction_on p
id └───────────────┘ ┴
src └───────────────┘
typ └───────────────┘ ┴
346 (λ b, rfl)
id ┴ └─┘
src └─┘
typ ┴ └─┘
347 (λ x t₁ t₂ p r b, by simp; rw [r b])
id ┴ └┘ └┘ ┴ ┴ ┴ ┴ ┴
src └──┘ └──┘ ┴ ┴
typ ┴ └┘ └┘ ┴ ┴ ┴ └──┘ └──┘┴┴┴┴
doc └──┘ └──┘ ┴ ┴
txt └──┘ └──┘ ┴ ┴
par └──┘ └──┘ ┴ ┴
pid └┘ ┴ ┴
st └─────────┘└─┘┴
348 (λ x y t₁ t₂ p r b, by simp; rw [lcomm, r b])
id ┴ ┴ └┘ └┘ ┴ ┴ ┴ └───┘ ┴ ┴
src └──┘ └──┘ └┘ ┴ ┴
typ ┴ ┴ └┘ └┘ ┴ ┴ ┴ └──┘ └──┘└───┘└┘┴┴┴┴
doc └──┘ └──┘ └┘ ┴ ┴
txt └──┘ └──┘ └┘ ┴ ┴
par └──┘ └──┘ └┘ ┴ ┴
pid └┘ └┘ ┴ ┴
st └─────────┘└───┘└───┘┴
349 (λ t₁ t₂ t₃ p₁ p₂ r₁ r₂ a, eq.trans (r₁ a) (r₂ a))
id └┘ └┘ └┘ └┘ └┘ └┘ └┘ ┴ └──────┘ └┘ ┴ └┘ ┴
src └──────┘
typ └┘ └┘ └┘ └┘ └┘ └┘ └┘ ┴ └──────┘ └┘ ┴ └┘ ┴
350
351 lemma rec_heq_of_perm {β : list α → Sort*} {f : Πa l, β l → β (a::l)} {b : β []} {l l' : list α}
id └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴└┘┴ ┴ └┘ └──┘ ┴
src └──┘ └┘ └┘ └──┘
typ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴└┘┴ ┴ └┘ └──┘ ┴
352 (hl : perm l l')
id └──┘ ┴ └┘
src └──┘
typ └──┘ ┴ └┘
doc └──┘
353 (f_congr : ∀{a l l' b b'}, perm l l' → b == b' → f a l b == f a l' b')
id ┴ ┴ └┘ ┴ └┘ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘ └┘
src └──┘ └┘ └┘
typ ┴ ┴ └┘ ┴ └┘ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ └┘ └┘
doc └──┘
354 (f_swap : ∀{a a' l b}, f a (a'::l) (f a' l b) == f a' (a::l) (f a l b)) :
id ┴ └┘ ┴ ┴ ┴ ┴ └┘└┘┴ ┴ └┘ ┴ ┴ └┘ ┴ └┘ ┴└┘┴ ┴ ┴ ┴ ┴
src └┘ └┘ └┘
typ ┴ └┘ ┴ ┴ ┴ ┴ └┘└┘┴ ┴ └┘ ┴ ┴ └┘ ┴ └┘ ┴└┘┴ ┴ ┴ ┴ ┴
355 @list.rec α β b f l == @list.rec α β b f l' :=
id └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ └──────┘ ┴ ┴ ┴ ┴ └┘
src └──────┘ └┘ └──────┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ └┘ └──────┘ ┴ ┴ ┴ ┴ └┘
356 begin
st └─────
357 induction hl,
id └┘
src └────────┘
typ └────────┘└┘
doc └────────┘
txt └────────┘
par └────────┘
pid ┴
st ─────────────┘└─
358 case list.perm.nil { refl },
src └───────────────────┘└───┘┴
typ └───────────────────┘└───┘┴
doc └───────────────────┘└───┘┴
txt └───────────────────┘└───┘┴
par └───────────────────┘└───┘┴
pid └────────────┘┴└──────┘
st ─────────────────────┘└────┘└┘└
359 case list.perm.skip : a l l' h ih { exact f_congr h ih },
id └─────┘ ┴ └┘
src └──────────────────────────────────┘└────┘ ┴ ┴ ┴┴
typ └──────────────────────────────────┘└────┘└─────┘┴┴┴└┘┴┴
doc └──────────────────────────────────┘└────┘ ┴ ┴ ┴┴
txt └──────────────────────────────────┘└────┘ ┴ ┴ ┴┴
par └──────────────────────────────────┘└────┘ ┴ ┴ ┴┴
pid └─────────────┘└────────────┘└───────┘ ┴ ┴ └┘
st ────────────────────────────────────┘└──────────────────┘└┘└
360 case list.perm.swap : a a' l { exact f_swap },
id └────┘
src └─────────────────────────────┘└────┘ ┴┴
typ └─────────────────────────────┘└────┘└────┘┴┴
doc └─────────────────────────────┘└────┘ ┴┴
txt └─────────────────────────────┘└────┘ ┴┴
par └─────────────────────────────┘└────┘ ┴┴
pid └─────────────┘└───────┘└───────┘ └┘
st ───────────────────────────────┘└────────────┘└┘└
361 case list.perm.trans : l₁ l₂ l₃ h₁ h₂ ih₁ ih₂ { exact heq.trans ih₁ ih₂ }
id └───────┘ └─┘ └─┘
src └──────────────────────────────────────────────┘└────┘└───────┘┴ ┴ ┴└┘
typ └──────────────────────────────────────────────┘└────┘└───────┘┴└─┘┴└─┘┴└┘
doc └──────────────────────────────────────────────┘└────┘ ┴ ┴ ┴└┘
txt └──────────────────────────────────────────────┘└────┘ ┴ ┴ ┴└┘
par └──────────────────────────────────────────────┘└────┘ ┴ ┴ ┴└┘
pid └──────────────┘└───────────────────────┘└───────┘ ┴ ┴ └┘┴
st ────────────────────────────────────────────────┘└───────────────────────┘┴┴
362 end
st └─┘
363
364 section
365 variables {op : α → α → α} [is_associative α op] [is_commutative α op]
id └────────────┘ └────────────┘
src └────────────┘ └────────────┘
typ └────────────┘ └────────────┘
366 local notation a * b := op a b
367 local notation l <*> a := foldl op a l
id └───┘
src └───┘
typ └───┘
368
369 lemma fold_op_eq_of_perm {l₁ l₂ : list α} {a : α} (h : l₁ ~ l₂) : l₁ <*> a = l₂ <*> a :=
id └──┘ ┴ ┴ └┘ ┴ └┘ └┘ └─┘ ┴ ┴ └┘ └─┘ ┴
src └──┘ ┴ └─┘ ┴ └─┘
typ └──┘ ┴ ┴ └┘ ┴ └┘ └┘ └─┘ ┴ ┴ └┘ └─┘ ┴
doc ┴
370 foldl_eq_of_perm (right_comm _ (is_commutative.comm _) (is_associative.assoc _)) h _
id └──────────────┘ └────────┘ └─────────────────┘ └──────────────────┘ ┴
src └──────────────┘ └────────┘ └─────────────────┘ └──────────────────┘
typ └──────────────┘ └────────┘ └─────────────────┘ └──────────────────┘ ┴
371 end
372
373 section comm_monoid
374 open list
375 variable [comm_monoid α]
id └─────────┘
src └─────────┘
typ └─────────┘
376
377 @[to_additive]
doc └─────────┘
378 lemma prod_eq_of_perm {l₁ l₂ : list α} (h : perm l₁ l₂) : prod l₁ = prod l₂ :=
id └──┘ ┴ └──┘ └┘ └┘ └──┘ └┘ ┴ └──┘ └┘
src └──┘ └──┘ └──┘ ┴ └──┘
typ └──┘ ┴ └──┘ └┘ └┘ └──┘ └┘ ┴ └──┘ └┘
doc └──┘ └──┘ └──┘
379 by induction h; simp [*, mul_left_comm]
id ┴ └───────────┘
src └────────┘ └───────┘└───────────┘└─
typ └────────┘┴ └───────┘└───────────┘└─
doc └────────┘ └───────┘ └─
txt └────────┘ └───────┘ └─
par └────────┘ └───────┘ └─
pid ┴ ┴└──┘ ┴└
st └─────────────────────────────────────
380
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
381 @[to_additive]
doc └─────────┘
382 lemma prod_reverse (l : list α) : prod l.reverse = prod l :=
id └──┘ ┴ └──┘ ┴└──────┘ ┴ └──┘ ┴
src └──┘ └──┘ └──────┘ ┴ └──┘
typ └──┘ ┴ └──┘ ┴└──────┘ ┴ └──┘ ┴
doc └──┘ └──┘
383 prod_eq_of_perm $ reverse_perm l
id └─────────────┘ └──────────┘ ┴
src └─────────────┘ └──────────┘
typ └─────────────┘ └──────────┘ ┴
384
385 end comm_monoid
386
387 theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : list α} : l₁++a::r₁ ~ l₂++a::r₂ → l₁++r₁ ~ l₂++r₂ :=
id ┴ └──┘ ┴ └┘└┘┴└┘└┘ ┴ └┘└┘┴└┘└┘ └┘└┘└┘ ┴ └┘└┘└┘
src └──┘ └┘ └┘ ┴ └┘ └┘ └┘ ┴ └┘
typ ┴ └──┘ ┴ └┘└┘┴└┘└┘ ┴ └┘└┘┴└┘└┘ └┘└┘└┘ ┴ └┘└┘└┘
doc ┴ ┴
388 begin
st └─────
389 generalize e₁ : l₁++a::r₁ = s₁, generalize e₂ : l₂++a::r₂ = s₂,
id └┘└┘┴ └┘ └┘ ┴ └┘
src └──────────────┘ └┘ ┴ ┴ └──────────────┘ ┴ ┴
typ └──────────────┘└┘└┘┴ └┘┴ ┴ └──────────────┘└┘ ┴ └┘┴ ┴
doc └──────────────┘ ┴ ┴ └──────────────┘ ┴ ┴
txt └──────────────┘ ┴ ┴ └──────────────┘ ┴ ┴
par └──────────────┘ ┴ ┴ └──────────────┘ ┴ ┴
pid └─┘└┘┴ ┴ ┴ └─┘└┘┴ ┴ ┴
st ───────────────────────────────┘└──────────────────────────────┘└─
390 intro p, revert l₁ l₂ r₁ r₂ e₁ e₂,
src └─────┘ └──────────────────────┘
typ └─────┘ └──────────────────────┘
doc └─────┘ └──────────────────────┘
txt └─────┘ └──────────────────────┘
par └─────┘ └──────────────────────┘
pid └┘ └────────────────┘
st ────────┘└────────────────────────┘└─
391 refine perm_induction_on p _ (λ x t₁ t₂ p IH, _) (λ x y t₁ t₂ p IH, _) (λ t₁ t₂ t₃ p₁ p₂ IH₁ IH₂, _);
id └───────────────┘ ┴
src └─────┘└───────────────┘┴ └─┘ └────────────────┘ └──────────────────┘ └─────────────────────────┘
typ └─────┘└───────────────┘┴┴└─┘ └────────────────┘ └──────────────────┘ └─────────────────────────┘
doc └─────┘ ┴ └─┘ └────────────────┘ └──────────────────┘ └─────────────────────────┘
txt └─────┘ ┴ └─┘ └────────────────┘ └──────────────────┘ └─────────────────────────┘
par └─────┘ ┴ └─┘ └────────────────┘ └──────────────────┘ └─────────────────────────┘
pid ┴ ┴ └─┘ └────────────────┘ └──────────────────┘ └─────────────────────────┘
st ────────────────────────────────────────────────────────────────────────────────────────────────────────
392 intros l₁ l₂ r₁ r₂ e₁ e₂,
src └──────────────────────┘
typ └──────────────────────┘
doc └──────────────────────┘
txt └──────────────────────┘
par └──────────────────────┘
pid └────────────────┘
st ───────────────────────────┘└─
393 { apply (not_mem_nil a).elim, rw ← e₁, simp },
id └─────────┘ ┴ └┘
src └────┘ └─────────┘┴ └────┘ └───┘ └───┘
typ └────┘ └─────────┘┴┴└────┘ └───┘└┘ └───┘
doc └────┘ ┴ └────┘ └───┘ └───┘
txt └────┘ ┴ └────┘ └───┘ └───┘
par └────┘ ┴ └────┘ └───┘ └───┘
pid ┴ ┴ └───┘┴ └─┘ ┴
st ───┘└────────────────────────┘└───────┘└─────┘└┘└
394 { cases l₁ with y l₁; cases l₂ with z l₂;
id └┘ └┘
src └────┘ └────────┘ └────┘ └────────┘
typ └────┘└┘└────────┘ └────┘└┘└────────┘
doc └────┘ └────────┘ └────┘ └────────┘
txt └────┘ └────────┘ └────┘ └────────┘
par └────┘ └────────┘ └────┘ └────────┘
pid ┴ └────────┘ ┴ └────────┘
st ───┘└───────────────────────────────────────
395 dsimp at e₁ e₂; injections; subst x,
id ┴
src └────────────┘ └────────┘ └────┘
typ └────────────┘ └────────┘ └────┘┴
doc └────────────┘ └────────┘ └────┘
txt └────────────┘ └────────┘ └────┘
par └────────────┘ └────────┘ └────┘
pid ┴└──────┘ ┴
st ────────────────────────────────────────┘└─
396 { substs t₁ t₂, exact p },
id ┴
src └──────────┘ └────┘ ┴
typ └──────────┘ └────┘┴┴
doc └──────────┘ └────┘ ┴
txt └──────────┘ └────┘ ┴
par └──────────┘ └────┘ ┴
pid └────┘ ┴ ┴
st ─────┘└──────────┘└────────────┘└┘└
397 { substs z t₁ t₂, exact p.trans perm_middle },
id └─────┘ └─────────┘
src └────────────┘ └────┘└─────┘┴└─────────┘┴
typ └────────────┘ └────┘└─────┘┴└─────────┘┴
doc └────────────┘ └────┘ ┴ ┴
txt └────────────┘ └────┘ ┴ ┴
par └────────────┘ └────┘ ┴ ┴
pid └──────┘ ┴ ┴ ┴
st ─────┘└────────────┘└────────────────────────────┘└┘└
398 { substs y t₁ t₂, exact perm_middle.symm.trans p },
id └────────────────────┘ ┴
src └────────────┘ └────┘└────────────────────┘┴ ┴
typ └────────────┘ └────┘└────────────────────┘┴┴┴
doc └────────────┘ └────┘ ┴ ┴
txt └────────────┘ └────┘ ┴ ┴
par └────────────┘ └────┘ ┴ ┴
pid └──────┘ ┴ ┴ ┴
st ─────┘└────────────┘└─────────────────────────────────┘└┘└
399 { substs z t₁ t₂, exact skip y (IH rfl rfl) } },
id └──┘ ┴ └┘ └─┘
src └────────────┘ └────┘└──┘┴ ┴ ┴ ┴└─┘└┘
typ └────────────┘ └────┘└──┘┴┴┴ └┘┴ ┴└─┘└┘
doc └────────────┘ └────┘ ┴ ┴ ┴ ┴ └┘
txt └────────────┘ └────┘ ┴ ┴ ┴ ┴ └┘
par └────────────┘ └────┘ ┴ ┴ ┴ ┴ └┘
pid └──────┘ ┴ ┴ ┴ ┴ ┴ ┴┴
st ───────────────────┘└────────────────────────────┘└──┘└
400 { rcases l₁ with _|⟨y, _|⟨z, l₁⟩⟩; rcases l₂ with _|⟨u, _|⟨v, l₂⟩⟩;
id └┘ └┘
src └─────┘ └────────────────────┘ └─────┘ └────────────────────┘
typ └─────┘└┘└────────────────────┘ └─────┘└┘└────────────────────┘
doc └─────┘ └────────────────────┘ └─────┘ └────────────────────┘
txt └─────┘ └────────────────────┘ └─────┘ └────────────────────┘
par └─────┘ └────────────────────┘ └─────┘ └────────────────────┘
pid ┴ └────────────────────┘ ┴ └────────────────────┘
st ───┘└─────────────────────────────────────────────────────────────────
401 dsimp at e₁ e₂; injections; substs x y,
src └────────────┘ └────────┘ └────────┘
typ └────────────┘ └────────┘ └────────┘
doc └────────────┘ └────────┘ └────────┘
txt └────────────┘ └────────┘ └────────┘
par └────────────┘ └────────┘ └────────┘
pid ┴└──────┘ └──┘
st ───────────────────────────────────────────┘└─
402 { substs r₁ r₂, exact skip a p },
id └──┘ ┴ ┴
src └──────────┘ └────┘└──┘┴ ┴ ┴
typ └──────────┘ └────┘└──┘┴┴┴┴┴
doc └──────────┘ └────┘ ┴ ┴ ┴
txt └──────────┘ └────┘ ┴ ┴ ┴
par └──────────┘ └────┘ ┴ ┴ ┴
pid └────┘ ┴ ┴ ┴ ┴
st ─────┘└──────────┘└───────────────────┘└┘└
403 { substs r₁ r₂, exact skip u p },
id └──┘ ┴ ┴
src └──────────┘ └────┘└──┘┴ ┴ ┴
typ └──────────┘ └────┘└──┘┴┴┴┴┴
doc └──────────┘ └────┘ ┴ ┴ ┴
txt └──────────┘ └────┘ ┴ ┴ ┴
par └──────────┘ └────┘ ┴ ┴ ┴
pid └────┘ ┴ ┴ ┴ ┴
st ─────┘└──────────┘└───────────────────┘└┘└
404 { substs r₁ v t₂, exact skip u (p.trans perm_middle) },
id └──┘ ┴ └─────┘ └─────────┘
src └────────────┘ └────┘└──┘┴ ┴ └─────┘┴└─────────┘└┘
typ └────────────┘ └────┘└──┘┴┴┴ └─────┘┴└─────────┘└┘
doc └────────────┘ └────┘ ┴ ┴ ┴ └┘
txt └────────────┘ └────┘ ┴ ┴ ┴ └┘
par └────────────┘ └────┘ ┴ ┴ ┴ └┘
pid └──────┘ ┴ ┴ ┴ ┴ ┴┴
st ─────┘└────────────┘└─────────────────────────────────────┘└┘└
405 { substs r₁ r₂, exact skip y p },
id └──┘ ┴ ┴
src └──────────┘ └────┘└──┘┴ ┴ ┴
typ └──────────┘ └────┘└──┘┴┴┴┴┴
doc └──────────┘ └────┘ ┴ ┴ ┴
txt └──────────┘ └────┘ ┴ ┴ ┴
par └──────────┘ └────┘ ┴ ┴ ┴
pid └────┘ ┴ ┴ ┴ ┴
st ─────┘└──────────┘└───────────────────┘└┘└
406 { substs r₁ r₂ y u, exact skip a p },
id └──┘ ┴ ┴
src └──────────────┘ └────┘└──┘┴ ┴ ┴
typ └──────────────┘ └────┘└──┘┴┴┴┴┴
doc └──────────────┘ └────┘ ┴ ┴ ┴
txt └──────────────┘ └────┘ ┴ ┴ ┴
par └──────────────┘ └────┘ ┴ ┴ ┴
pid └────────┘ ┴ ┴ ┴ ┴
st ─────┘└──────────────┘└───────────────┘└┘└
407 { substs r₁ u v t₂, exact (skip y $ p.trans perm_middle).trans (swap _ _ _) },
id └──┘ ┴ └─────┘ └─────────┘ └──┘
src └──────────────┘ └────┘ └──┘┴ ┴ ┴└─────┘┴└─────────┘└──────┘ └──┘└──────┘
typ └──────────────┘ └────┘ └──┘┴┴┴ ┴└─────┘┴└─────────┘└──────┘ └──┘└──────┘
doc └──────────────┘ └────┘ ┴ ┴ ┴ ┴ └──────┘ └──────┘
txt └──────────────┘ └────┘ ┴ ┴ ┴ ┴ └──────┘ └──────┘
par └──────────────┘ └────┘ ┴ ┴ ┴ ┴ └──────┘ └──────┘
pid └────────┘ ┴ ┴ ┴ ┴ ┴ └──────┘ └─────┘┴
st ─────┘└──────────────┘└────────────────────────────────────────────────────────┘└┘└
408 { substs r₂ z t₁, exact skip y (perm_middle.symm.trans p) },
id └──┘ ┴ └────────────────────┘ ┴
src └────────────┘ └────┘└──┘┴ ┴ └────────────────────┘┴ └┘
typ └────────────┘ └────┘└──┘┴┴┴ └────────────────────┘┴┴└┘
doc └────────────┘ └────┘ ┴ ┴ ┴ └┘
txt └────────────┘ └────┘ ┴ ┴ ┴ └┘
par └────────────┘ └────┘ ┴ ┴ ┴ └┘
pid └──────┘ ┴ ┴ ┴ ┴ ┴┴
st ─────┘└────────────┘└──────────────────────────────────────────┘└┘└
409 { substs r₂ y z t₁, exact (swap _ _ _).trans (skip u $ perm_middle.symm.trans p) },
id └──┘ └──┘ ┴ └────────────────────┘ ┴
src └──────────────┘ └────┘ └──┘└────────────┘ └──┘┴ ┴ ┴└────────────────────┘┴ └┘
typ └──────────────┘ └────┘ └──┘└────────────┘ └──┘┴┴┴ ┴└────────────────────┘┴┴└┘
doc └──────────────┘ └────┘ └────────────┘ ┴ ┴ ┴ ┴ └┘
txt └──────────────┘ └────┘ └────────────┘ ┴ ┴ ┴ ┴ └┘
par └──────────────┘ └────┘ └────────────┘ ┴ ┴ ┴ ┴ └┘
pid └────────┘ ┴ └────────────┘ ┴ ┴ ┴ ┴ ┴┴
st ─────┘└──────────────┘└─────────────────────────────────────────────────────────────┘└┘└
410 { substs u v t₁ t₂, exact (IH rfl rfl).swap' _ _ } },
id └┘ └─┘
src └──────────────┘ └────┘ ┴ ┴└─┘└──────────┘
typ └──────────────┘ └────┘ └┘┴ ┴└─┘└──────────┘
doc └──────────────┘ └────┘ ┴ ┴ └──────────┘
txt └──────────────┘ └────┘ ┴ ┴ └──────────┘
par └──────────────┘ └────┘ ┴ ┴ └──────────┘
pid └────────┘ ┴ ┴ ┴ └─────────┘┴
st ─────────────────────┘└─────────────────────────────┘└──┘└
411 { substs t₁ t₃,
src └──────────┘
typ └──────────┘
doc └──────────┘
txt └──────────┘
par └──────────┘
pid └────┘
st ───────────────┘└─
412 have : a ∈ t₂ := perm_subset p₁ (by simp),
id ┴ ┴ └┘ └─────────┘ └┘
src └─────┘ ┴┴┴ └──┘└─────────┘┴ ┴ ┴└──┘┴
typ └─────┘┴┴┴┴└┘└──┘└─────────┘┴└┘┴ ┴└──┘┴
doc └─────┘ ┴ ┴ └──┘ ┴ ┴ ┴└──┘┴
txt └─────┘ ┴ ┴ └──┘ ┴ ┴ ┴└──┘┴
par └─────┘ ┴ ┴ └──┘ ┴ ┴ ┴└──┘┴
pid └───┘└┘ ┴ ┴ └──┘ ┴ ┴ └────┘
st ──────────────────────────────────────┘└───┘┴└─
413 rcases mem_split this with ⟨l₂, r₂, e₂⟩,
id └───────┘ └──┘
src └─────┘└───────┘┴ └────────────────┘
typ └─────┘└───────┘┴└──┘└────────────────┘
doc └─────┘ ┴ └────────────────┘
txt └─────┘ ┴ └────────────────┘
par └─────┘ ┴ └────────────────┘
pid ┴ ┴ └────────────────┘
st ──────────────────────────────────────────┘└─
414 subst t₂, exact (IH₁ rfl rfl).trans (IH₂ rfl rfl) }
id └┘ └─┘ └─┘ └─┘
src └────┘ └────┘ ┴ ┴ └──────┘ ┴ ┴└─┘└┘
typ └────┘└┘ └────┘ └─┘┴ ┴ └──────┘ └─┘┴ ┴└─┘└┘
doc └────┘ └────┘ ┴ ┴ └──────┘ ┴ ┴ └┘
txt └────┘ └────┘ ┴ ┴ └──────┘ ┴ ┴ └┘
par └────┘ └────┘ ┴ ┴ └──────┘ ┴ ┴ └┘
pid ┴ ┴ ┴ ┴ └──────┘ ┴ ┴ ┴┴
st ───────────┘└────────────────────────────────────────┘└─
415 end
st ──┘
416
417 theorem perm_cons_inv {a : α} {l₁ l₂ : list α} : a::l₁ ~ a::l₂ → l₁ ~ l₂ :=
id ┴ └──┘ ┴ ┴└┘└┘ ┴ ┴└┘└┘ └┘ ┴ └┘
src └──┘ └┘ ┴ └┘ ┴
typ ┴ └──┘ ┴ ┴└┘└┘ ┴ ┴└┘└┘ └┘ ┴ └┘
doc ┴ ┴
418 @perm_inv_core _ _ [] [] _ _
id └───────────┘ └┘ └┘
src └───────────┘ └┘ └┘
typ └───────────┘ └┘ └┘
419
420 theorem perm_cons (a : α) {l₁ l₂ : list α} : a::l₁ ~ a::l₂ ↔ l₁ ~ l₂ :=
id ┴ └──┘ ┴ ┴└┘└┘ ┴ ┴└┘└┘ ┴ └┘ ┴ └┘
src └──┘ └┘ ┴ └┘ ┴ ┴
typ ┴ └──┘ ┴ ┴└┘└┘ ┴ ┴└┘└┘ ┴ └┘ ┴ └┘
doc ┴ ┴
421 ⟨perm_cons_inv, skip a⟩
id └───────────┘ └──┘ ┴
src └───────────┘ └──┘
typ └───────────┘ └──┘ ┴
422
423 theorem perm_app_left_iff {l₁ l₂ : list α} : ∀ l, l++l₁ ~ l++l₂ ↔ l₁ ~ l₂
id └──┘ ┴ ┴ ┴└┘└┘ ┴ ┴└┘└┘ ┴ └┘ ┴ └┘
src └──┘ └┘ ┴ └┘ ┴ ┴
typ └──┘ ┴ ┴ ┴└┘└┘ ┴ ┴└┘└┘ ┴ └┘ ┴ └┘
doc ┴ ┴
424 | [] := iff.rfl
id └┘ └─────┘
src └┘ └─────┘
typ └┘ └─────┘
425 | (a::l) := (perm_cons a).trans (perm_app_left_iff l)
id ┴└┘┴ └───────┘ └───┘ └───────────────┘
src └┘ └───────┘ └───┘
typ ┴└┘┴ └───────┘ └───┘ └───────────────┘
426
427 theorem perm_app_right_iff {l₁ l₂ : list α} (l) : l₁++l ~ l₂++l ↔ l₁ ~ l₂ :=
id └──┘ ┴ └┘└┘┴ ┴ └┘└┘┴ ┴ └┘ ┴ └┘
src └──┘ └┘ ┴ └┘ ┴ ┴
typ └──┘ ┴ └┘└┘┴ ┴ └┘└┘┴ ┴ └┘ ┴ └┘
doc ┴ ┴
428 ⟨λ p, (perm_app_left_iff _).1 $ trans perm_app_comm $ trans p perm_app_comm,
id ┴ └───────────────┘ ┴ └───┘ └───────────┘ └───┘ ┴ └───────────┘
src └───────────────┘ ┴ └───┘ └───────────┘ └───┘ └───────────┘
typ ┴ └───────────────┘ ┴ └───┘ └───────────┘ └───┘ ┴ └───────────┘
429 perm_app_left _⟩
id └───────────┘
src └───────────┘
typ └───────────┘
430
431 theorem perm_option_to_list {o₁ o₂ : option α} : o₁.to_list ~ o₂.to_list ↔ o₁ = o₂ :=
id └────┘ ┴ └┘└──────┘ ┴ └┘└──────┘ ┴ └┘ ┴ └┘
src └────┘ └──────┘ ┴ └──────┘ ┴ ┴
typ └────┘ ┴ └┘└──────┘ ┴ └┘└──────┘ ┴ └┘ ┴ └┘
doc ┴
432 begin
st └─────
433 refine ⟨λ p, _, λ e, e ▸ perm.refl _⟩,
id ┴ └───────┘
src └─────┘ └─────┘ └──┘ ┴┴┴└───────┘└─┘
typ └─────┘ └─────┘ └──┘ ┴┴┴└───────┘└─┘
doc └─────┘ └─────┘ └──┘ ┴ ┴ └─┘
txt └─────┘ └─────┘ └──┘ ┴ ┴ └─┘
par └─────┘ └─────┘ └──┘ ┴ ┴ └─┘
pid ┴ └─────┘ └──┘ ┴ ┴ └─┘
st ──────────────────────────────────────┘└─
434 cases o₁ with a; cases o₂ with b, {refl},
id └┘ └┘
src └────┘ └─────┘ └────┘ └─────┘ └──┘
typ └────┘└┘└─────┘ └────┘└┘└─────┘ └──┘
doc └────┘ └─────┘ └────┘ └─────┘ └──┘
txt └────┘ └─────┘ └────┘ └─────┘ └──┘
par └────┘ └─────┘ └────┘ └─────┘ └──┘
pid ┴ └─────┘ ┴ └─────┘
st ─────────────────────────────────┘└─────┘└┘└
435 { cases (perm_length p) },
id └─────────┘ ┴
src └────┘ └─────────┘┴ └┘
typ └────┘ └─────────┘┴┴└┘
doc └────┘ ┴ └┘
txt └────┘ ┴ └┘
par └────┘ ┴ └┘
pid ┴ ┴ ┴┴
st ───┘└────────────────────┘└┘└
436 { cases (perm_length p) },
id └─────────┘ ┴
src └────┘ └─────────┘┴ └┘
typ └────┘ └─────────┘┴┴└┘
doc └────┘ ┴ └┘
txt └────┘ ┴ └┘
par └────┘ ┴ └┘
pid ┴ ┴ ┴┴
st ───┘└────────────────────┘└┘└
437 { exact option.mem_to_list.1 ((mem_of_perm p).2 $ by simp) }
id └────────────────┘ └─────────┘ ┴
src └────┘└────────────────┘└─┘ └─────────┘┴ └──┘ ┴ ┴└──┘└┘
typ └────┘└────────────────┘└─┘ └─────────┘┴┴└──┘ ┴ ┴└──┘└┘
doc └────┘ └─┘ ┴ └──┘ ┴ ┴└──┘└┘
txt └────┘ └─┘ ┴ └──┘ ┴ ┴└──┘└┘
par └────┘ └─┘ ┴ └──┘ ┴ ┴└──┘└┘
pid ┴ └─┘ ┴ └──┘ ┴ └────┘┴
st ─────────────────────────────────────────────────────┘└───┘└┘└─
438 end
st ──┘
439
440 theorem subperm_cons (a : α) {l₁ l₂ : list α} : a::l₁ <+~ a::l₂ ↔ l₁ <+~ l₂ :=
id ┴ └──┘ ┴ ┴└┘└┘ └─┘ ┴└┘└┘ ┴ └┘ └─┘ └┘
src └──┘ └┘ └─┘ └┘ ┴ └─┘
typ ┴ └──┘ ┴ ┴└┘└┘ └─┘ ┴└┘└┘ ┴ └┘ └─┘ └┘
doc └─┘ └─┘
441 ⟨λ ⟨l, p, s⟩, begin
id ┴
typ ┴
st └─────
442 cases s with _ _ _ s' u _ _ s',
id ┴
src └────┘ └─────────────────────┘
typ └────┘┴└─────────────────────┘
doc └────┘ └─────────────────────┘
txt └────┘ └─────────────────────┘
par └────┘ └─────────────────────┘
pid ┴ └─────────────────────┘
st ───────────────────────────────┘└─
443 { exact (p.subperm_left.2 $ subperm_of_sublist $ sublist_cons _ _).trans
id └────────────┘ └──────────┘
src └────┘ └────────────┘└─┘ ┴ ┴ ┴└──────────┘└───────────
typ └────┘ └────────────┘└─┘ ┴ ┴ ┴└──────────┘└───────────
doc └────┘ └─┘ ┴ ┴ ┴ └───────────
txt └────┘ └─┘ ┴ ┴ ┴ └───────────
par └────┘ └─┘ ┴ ┴ ┴ └───────────
pid ┴ └─┘ ┴ ┴ ┴ └───────────
st ───┘└──────────────────────────────────────────────────────────────────────
444 (subperm_of_sublist s') },
id └────────────────┘ └┘
src ────┘ └────────────────┘┴ └┘
typ ────┘ └────────────────┘┴└┘└┘
doc ────┘ ┴ └┘
txt ────┘ ┴ └┘
par ────┘ ┴ └┘
pid ────┘ ┴ ┴┴
st ────────────────────────────┘└┘└
445 { exact ⟨u, perm_cons_inv p, s'⟩ }
id ┴ └───────────┘ ┴ └┘
src └────┘ └┘└───────────┘┴ └┘ └┘
typ └────┘ ┴└┘└───────────┘┴┴└┘└┘└┘
doc └────┘ └┘ ┴ └┘ └┘
txt └────┘ └┘ ┴ └┘ └┘
par └────┘ └┘ ┴ └┘ └┘
pid ┴ └┘ ┴ └┘ ┴┴
st ──────────────────────────────────┘└─
446 end, λ ⟨l, p, s⟩, ⟨a::l, skip a p, s.cons2 _ _ _⟩⟩
id ┴┴ ┴ ┴ ┴└┘ └──┘ ┴ └────┘
src └┘ └──┘ └────┘
typ ┴┴ ┴ ┴ ┴└┘ └──┘ ┴ └────┘
st ──┘
447
448 theorem cons_subperm_of_mem {a : α} {l₁ l₂ : list α} (d₁ : nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
id ┴ └──┘ ┴ └───┘ └┘ ┴ ┴ └┘ ┴ ┴ └┘
src └──┘ └───┘ ┴ ┴
typ ┴ └──┘ ┴ └───┘ └┘ ┴ ┴ └┘ ┴ ┴ └┘
doc └───┘
449 (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ :=
id └┘ └─┘ └┘ ┴ └┘ └┘ └─┘ └┘
src └─┘ └┘ └─┘
typ └┘ └─┘ └┘ ┴ └┘ └┘ └─┘ └┘
doc └─┘ └─┘
450 begin
st └─────
451 rcases s with ⟨l, p, s⟩,
id ┴
src └─────┘ └─────────────┘
typ └─────┘┴└─────────────┘
doc └─────┘ └─────────────┘
txt └─────┘ └─────────────┘
par └─────┘ └─────────────┘
pid ┴ └─────────────┘
st ────────────────────────┘└─
452 induction s generalizing l₁,
id ┴
src └────────┘ └──────────────┘
typ └────────┘┴└──────────────┘
doc └────────┘ └──────────────┘
txt └────────┘ └──────────────┘
par └────────┘ └──────────────┘
pid ┴ ┴└─────────────┘
st ────────────────────────────┘└─
453 case list.sublist.slnil { cases h₂ },
id └┘
src └────────────────────────┘└────┘ ┴┴
typ └────────────────────────┘└────┘└┘┴┴
doc └────────────────────────┘└────┘ ┴┴
txt └────────────────────────┘└────┘ ┴┴
par └────────────────────────┘└────┘ ┴┴
pid └─────────────────┘┴└──────┘ └┘
st ──────────────────────────┘└────────┘└┘└
454 case list.sublist.cons : r₁ r₂ b s' ih {
src └────────────────────────────────────────
typ └────────────────────────────────────────
doc └────────────────────────────────────────
txt └────────────────────────────────────────
par └────────────────────────────────────────
pid └────────────────┘└──────────────┘└──
st ─────────────────────────────────────────┘└
455 simp at h₂,
src ───┘└────────┘└─
typ ───┘└────────┘└─
doc ───┘└────────┘└─
txt ───┘└────────┘└─
par ───┘└────────┘└─
pid ────────────────
st ─────────────┘└─
456 cases h₂ with e m,
id └┘
src ───┘└────┘ └───────┘└─
typ ───┘└────┘└┘└───────┘└─
doc ───┘└────┘ └───────┘└─
txt ───┘└────┘ └───────┘└─
par ───┘└────┘ └───────┘└─
pid ─────────┘ └──────────
st ────────────────────┘└─
457 { subst b, exact ⟨a::r₁, skip a p, s'.cons2 _ _ _⟩ },
id ┴ └┘ └──┘ ┴ ┴ └──────┘
src ─────┘└────┘ └┘└────┘ └┘└──┘┴ ┴ └┘└──────┘└──────┘└──
typ ─────┘└────┘┴└┘└────┘ └┘└┘└──┘┴┴┴┴└┘└──────┘└──────┘└──
doc ─────┘└────┘ └┘└────┘ └┘ ┴ ┴ └┘ └──────┘└──
txt ─────┘└────┘ └┘└────┘ └┘ ┴ ┴ └┘ └──────┘└──
par ─────┘└────┘ └┘└────┘ └┘ ┴ ┴ └┘ └──────┘└──
pid ───────────┘ └──────┘ └┘ ┴ ┴ └┘ └──────────
st ────┘└──────┘└────────────────────────────────────────┘┴└─
458 { rcases ih m d₁ h₁ p with ⟨t, p', s'⟩, exact ⟨t, p', s'.cons _ _ _⟩ } },
id └┘ ┴ └┘ └┘ ┴ ┴ └┘ └─────┘
src ─────┘└─────┘ ┴ ┴ ┴ ┴ └───────────────┘└┘└────┘ └┘ └┘└─────┘└──────┘└─┘
typ ─────┘└─────┘└┘┴┴┴└┘┴└┘┴┴└───────────────┘└┘└────┘ ┴└┘└┘└┘└─────┘└──────┘└─┘
doc ─────┘└─────┘ ┴ ┴ ┴ ┴ └───────────────┘└┘└────┘ └┘ └┘ └──────┘└─┘
txt ─────┘└─────┘ ┴ ┴ ┴ ┴ └───────────────┘└┘└────┘ └┘ └┘ └──────┘└─┘
par ─────┘└─────┘ ┴ ┴ ┴ ┴ └───────────────┘└┘└────┘ └┘ └┘ └──────┘└─┘
pid ────────────┘ ┴ ┴ ┴ ┴ └───────────────────────┘ └┘ └┘ └─────────┘
st ─────────────────────────────────────────┘└─────────────────────────────┘└──┘└
459 case list.sublist.cons2 : r₁ r₂ b s' ih {
src └─────────────────────────────────────────
typ └─────────────────────────────────────────
doc └─────────────────────────────────────────
txt └─────────────────────────────────────────
par └─────────────────────────────────────────
pid └─────────────────┘└──────────────┘└──
st ──────────────────────────────────────────┘└
460 have bm : b ∈ l₁ := (perm_subset p $ mem_cons_self _ _),
id ┴ ┴ └┘ └─────────┘ ┴ └───────────┘
src ───┘└────────┘ ┴┴┴ └──┘ └─────────┘┴ ┴ ┴└───────────┘└───┘└─
typ ───┘└────────┘┴┴┴┴└┘└──┘ └─────────┘┴┴┴ ┴└───────────┘└───┘└─
doc ───┘└────────┘ ┴ ┴ └──┘ ┴ ┴ ┴ └───┘└─
txt ───┘└────────┘ ┴ ┴ └──┘ ┴ ┴ ┴ └───┘└─
par ───┘└────────┘ ┴ ┴ └──┘ ┴ ┴ ┴ └───┘└─
pid ─────────────┘ ┴ ┴ └──┘ ┴ ┴ ┴ └──────
st ──────────────────────────────────────────────────────────┘└─
461 have am : a ∈ r₂ := h₂.resolve_left (λ e, h₁ $ e.symm ▸ bm),
id ┴ └┘ └─────────────┘ └┘ └───┘ ┴ └┘
src ───┘└────────┘ ┴ ┴ └──┘└─────────────┘┴ └──┘ ┴ ┴ └───┘┴┴┴ ┴└─
typ ───┘└────────┘┴┴ ┴└┘└──┘└─────────────┘┴ └──┘└┘┴ ┴ └───┘┴┴┴└┘┴└─
doc ───┘└────────┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴└─
txt ───┘└────────┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴└─
par ───┘└────────┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴ ┴ ┴ ┴└─
pid ─────────────┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴ ┴ ┴ └──
st ──────────────────────────────────────────────────────────────┘└─
462 rcases mem_split bm with ⟨t₁, t₂, rfl⟩,
id └───────┘ └┘
src ───┘└─────┘└───────┘┴ └─────────────────┘└─
typ ───┘└─────┘└───────┘┴└┘└─────────────────┘└─
doc ───┘└─────┘ ┴ └─────────────────┘└─
txt ───┘└─────┘ ┴ └─────────────────┘└─
par ───┘└─────┘ ┴ └─────────────────┘└─
pid ──────────┘ ┴ └────────────────────
st ─────────────────────────────────────────┘└─
463 have st : t₁ ++ t₂ <+ t₁ ++ b :: t₂ := by simp,
id └┘ └┘ └┘ ┴ └┘
src ───┘└────────┘ ┴└┘┴ ┴└┘┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘└─
typ ───┘└────────┘ ┴└┘┴ ┴└┘┴└┘┴ ┴┴┴ ┴└┘└──┘ ┴└──┘└─
doc ───┘└────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘└─
txt ───┘└────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘└─
par ───┘└────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ ┴└──┘└─
pid ─────────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └──┘ └──────
st ────────────────────────────────────────────┘└───┘└─
464 rcases ih am (nodup_of_sublist st d₁)
id └┘ └┘ └──────────────┘ └┘
src ───┘└─────┘ ┴ ┴ └──────────────┘┴ ┴ └─
typ ───┘└─────┘└┘┴└┘┴ └──────────────┘┴ ┴└┘└─
doc ───┘└─────┘ ┴ ┴ ┴ ┴ └─
txt ───┘└─────┘ ┴ ┴ ┴ ┴ └─
par ───┘└─────┘ ┴ ┴ ┴ ┴ └─
pid ──────────┘ ┴ ┴ ┴ ┴ └─
st ──────────────────────────────────────────
465 (mt (λ x, subset_of_sublist st x) h₁)
id └┘ └───────────────┘ └┘ └┘
src ─────┘ └┘┴ └──┘└───────────────┘┴ ┴ └┘ └─
typ ─────┘ └┘┴ └──┘└───────────────┘┴└┘┴ └┘└┘└─
doc ─────┘ ┴ └──┘ ┴ ┴ └┘ └─
txt ─────┘ ┴ └──┘ ┴ ┴ └┘ └─
par ─────┘ ┴ └──┘ ┴ ┴ └┘ └─
pid ─────┘ ┴ └──┘ ┴ ┴ └┘ └─
st ────────────────────────────────────────────
466 (perm_cons_inv $ p.trans perm_middle) with ⟨t, p', s'⟩,
id └───────────┘ └─────┘ └─────────┘
src ─────┘ └───────────┘┴ ┴└─────┘┴└─────────┘└────────────────┘└─
typ ─────┘ └───────────┘┴ ┴└─────┘┴└─────────┘└────────────────┘└─
doc ─────┘ ┴ ┴ ┴ └────────────────┘└─
txt ─────┘ ┴ ┴ ┴ └────────────────┘└─
par ─────┘ ┴ ┴ ┴ └────────────────┘└─
pid ─────┘ ┴ ┴ ┴ └───────────────────
st ───────────────────────────────────────────────────────────┘└─
467 exact ⟨b::t, (skip b p').trans $ (swap _ _ _).trans (skip a perm_middle.symm), s'.cons2 _ _ _⟩ }
id ┴ ┴ └┘ └──┘ └──┘ ┴ └──────────────┘ └──────┘
src ───┘└────┘ └┘ ┴ ┴ └──────┘ ┴ └──┘└────────────┘ └──┘┴ ┴└──────────────┘└─┘└──────┘└──────┘└┘
typ ───┘└────┘ ┴└┘ ┴┴┴└┘└──────┘ ┴ └──┘└────────────┘ └──┘┴┴┴└──────────────┘└─┘└──────┘└──────┘└┘
doc ───┘└────┘ └┘ ┴ ┴ └──────┘ ┴ └────────────┘ ┴ ┴ └─┘ └──────┘└┘
txt ───┘└────┘ └┘ ┴ ┴ └──────┘ ┴ └────────────┘ ┴ ┴ └─┘ └──────┘└┘
par ───┘└────┘ └┘ ┴ ┴ └──────┘ ┴ └────────────┘ ┴ ┴ └─┘ └──────┘└┘
pid ─────────┘ └┘ ┴ ┴ └──────┘ ┴ └────────────┘ ┴ ┴ └─┘ └───────┘┴
st ──────────────────────────────────────────────────────────────────────────────────────────────────┘┴┴
468 end
st └─┘
469
470 theorem subperm_app_left {l₁ l₂ : list α} : ∀ l, l++l₁ <+~ l++l₂ ↔ l₁ <+~ l₂
id └──┘ ┴ ┴ ┴└┘└┘ └─┘ ┴└┘└┘ ┴ └┘ └─┘ └┘
src └──┘ └┘ └─┘ └┘ ┴ └─┘
typ └──┘ ┴ ┴ ┴└┘└┘ └─┘ ┴└┘└┘ ┴ └┘ └─┘ └┘
doc └─┘ └─┘
471 | [] := iff.rfl
id └┘ └─────┘
src └┘ └─────┘
typ └┘ └─────┘
472 | (a::l) := (subperm_cons a).trans (subperm_app_left l)
id ┴└┘┴ └──────────┘ └───┘ └──────────────┘
src └┘ └──────────┘ └───┘
typ ┴└┘┴ └──────────┘ └───┘ └──────────────┘
473
474 theorem subperm_app_right {l₁ l₂ : list α} (l) : l₁++l <+~ l₂++l ↔ l₁ <+~ l₂ :=
id └──┘ ┴ └┘└┘┴ └─┘ └┘└┘┴ ┴ └┘ └─┘ └┘
src └──┘ └┘ └─┘ └┘ ┴ └─┘
typ └──┘ ┴ └┘└┘┴ └─┘ └┘└┘┴ ┴ └┘ └─┘ └┘
doc └─┘ └─┘
475 (perm_app_comm.subperm_left.trans perm_app_comm.subperm_right).trans (subperm_app_left l)
id └───────────┘└───────────┘└────┘ └───────────┘└────────────┘ └───┘ └──────────────┘ ┴
src └───────────┘└───────────┘└────┘ └───────────┘└────────────┘ └───┘ └──────────────┘
typ └───────────┘└───────────┘└────┘ └───────────┘└────────────┘ └───┘ └──────────────┘ ┴
476
477 theorem subperm.exists_of_length_lt {l₁ l₂ : list α} :
id └──┘ ┴
src └──┘
typ └──┘ ┴
478 l₁ <+~ l₂ → length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
id └┘ └─┘ └┘ ┴ └────┘ └┘ ┴ └────┘ └┘ ┴ ┴┴ ┴ └┘ └┘ └─┘ └┘
src └─┘ └────┘ ┴ └────┘ ┴ ┴ └┘ └─┘
typ └┘ └─┘ └┘ ┴ └────┘ └┘ ┴ └────┘ └┘ ┴ ┴┴ ┴ └┘ └┘ └─┘ └┘
doc └─┘ └─┘
479 | ⟨l, p, s⟩ h :=
id ┴ ┴ ┴
typ ┴ ┴ ┴
480 suffices length l < length l₂ → ∃ (a : α), a :: l <+~ l₂, from
id └────┘ ┴ └────┘ └┘ ┴ ┴ ┴ ┴ └┘ └─┘ └┘
src └────┘ ┴ └────┘ ┴ ┴ └┘ └─┘
typ └────┘ ┴ └────┘ └┘ ┴ ┴ ┴ ┴ └┘ └─┘ └┘
doc └─┘
481 (this $ perm_length p.symm ▸ h).imp (λ a, (skip a p).subperm_right.1),
id └──┘ └─────────┘ └───┘ ┴ └─┘ ┴ └──┘ ┴ └───────────┘ ┴
src └─────────┘ └───┘ ┴ └─┘ └──┘ └───────────┘ ┴
typ └──┘ └─────────┘ └───┘ ┴ └─┘ ┴ └──┘ ┴ └───────────┘ ┴
482 begin
st └─────
483 clear subperm.exists_of_length_lt p h l₁, rename l₂ u,
src └──────────────────────────────────────┘ └─────────┘
typ └──────────────────────────────────────┘ └─────────┘
doc └──────────────────────────────────────┘ └─────────┘
txt └──────────────────────────────────────┘ └─────────┘
par └──────────────────────────────────────┘ └─────────┘
pid └─────────────────────────────────┘ └─┘└┘
st ───────────────────────────────────────────┘└───────────┘└─
484 induction s with l₁ l₂ a s IH _ _ b s IH; intro h,
id ┴
src └────────┘ └───────────────────────────┘ └─────┘
typ └────────┘┴└───────────────────────────┘ └─────┘
doc └────────┘ └───────────────────────────┘ └─────┘
txt └────────┘ └───────────────────────────┘ └─────┘
par └────────┘ └───────────────────────────┘ └─────┘
pid ┴ ┴└──────────────────────────┘ └┘
st ────────────────────────────────────────────────────┘└─
485 { cases h },
id ┴
src └────┘ ┴
typ └────┘┴┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴ ┴
st ─────┘└──────┘└┘└
486 { cases lt_or_eq_of_le (nat.le_of_lt_succ h : length l₁ ≤ length l₂) with h h,
id └────────────┘ └───────────────┘ ┴ └┘ ┴ └────┘ └┘
src └────┘└────────────┘┴ └───────────────┘┴ └─┘ ┴ ┴┴┴└────┘┴ └────────┘
typ └────┘└────────────┘┴ └───────────────┘┴┴└─┘ ┴└┘┴┴┴└────┘┴└┘└────────┘
doc └────┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ └────────┘
txt └────┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ └────────┘
par └────┘ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ └────────┘
pid ┴ ┴ ┴ └─┘ ┴ ┴ ┴ ┴ ┴└───────┘
st ─────┘└─────────────────────────────────────────────────────────────────────────┘└─
487 { exact (IH h).imp (λ a s, s.trans (subperm_of_sublist $ sublist_cons _ _)) },
id └┘ ┴ └────┘ └────────────────┘ └──────────┘
src └────┘ ┴ └────┘ └────┘ └────┘┴ └────────────────┘┴ ┴└──────────┘└─────┘
typ └────┘ └┘┴┴└────┘ └────┘ └────┘┴ └────────────────┘┴ ┴└──────────┘└─────┘
doc └────┘ ┴ └────┘ └────┘ ┴ ┴ ┴ └─────┘
txt └────┘ ┴ └────┘ └────┘ ┴ ┴ ┴ └─────┘
par └────┘ ┴ └────┘ └────┘ ┴ ┴ ┴ └─────┘
pid ┴ ┴ └────┘ └────┘ ┴ ┴ ┴ └────┘┴
st ───────┘└────────────────────────────────────────────────────────────────────────┘└┘└
488 { exact ⟨a, eq_of_sublist_of_length_eq s h ▸ subperm.refl _⟩ } },
id ┴ └────────────────────────┘ ┴ ┴ ┴ └──────────┘
src └────┘ └┘└────────────────────────┘┴ ┴ ┴┴┴└──────────┘└──┘
typ └────┘ ┴└┘└────────────────────────┘┴┴┴┴┴┴┴└──────────┘└──┘
doc └────┘ └┘ ┴ ┴ ┴ ┴ └──┘
txt └────┘ └┘ ┴ ┴ ┴ ┴ └──┘
par └────┘ └┘ ┴ ┴ ┴ ┴ └──┘
pid ┴ └┘ ┴ ┴ ┴ ┴ └─┘┴
st ──────────────────────────────────────────────────────────────────┘└──┘└
489 { exact (IH $ nat.lt_of_succ_lt_succ h).imp
id └┘ └────────────────────┘ ┴
src └────┘ ┴ ┴└────────────────────┘┴ └─────
typ └────┘ └┘┴ ┴└────────────────────┘┴┴└─────
doc └────┘ ┴ ┴ ┴ └─────
txt └────┘ ┴ ┴ ┴ └─────
par └────┘ ┴ ┴ ┴ └─────
pid ┴ ┴ ┴ ┴ └─────
st ────────────────────────────────────────────────
490 (λ a s, (swap _ _ _).subperm_right.1 $ (subperm_cons _).2 s) }
id └──┘ └──────────┘
src ───────┘ └────┘ └──┘└──────────────────────┘ ┴ └──────────┘└────┘ └┘
typ ───────┘ └────┘ └──┘└──────────────────────┘ ┴ └──────────┘└────┘ └┘
doc ───────┘ └────┘ └──────────────────────┘ ┴ └────┘ └┘
txt ───────┘ └────┘ └──────────────────────┘ ┴ └────┘ └┘
par ───────┘ └────┘ └──────────────────────┘ ┴ └────┘ └┘
pid ───────┘ └────┘ └──────────────────────┘ ┴ └────┘ ┴┴
st ────────────────────────────────────────────────────────────────────┘└─
491 end
st ────┘
492
493 theorem subperm_of_subset_nodup
494 {l₁ l₂ : list α} (d : nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ :=
id └──┘ ┴ └───┘ └┘ └┘ ┴ └┘ └┘ └─┘ └┘
src └──┘ └───┘ ┴ └─┘
typ └──┘ ┴ └───┘ └┘ └┘ ┴ └┘ └┘ └─┘ └┘
doc └───┘ └─┘
495 begin
st └─────
496 induction d with a l₁' h d IH,
id ┴
src └────────┘ └────────────────┘
typ └────────┘┴└────────────────┘
doc └────────┘ └────────────────┘
txt └────────┘ └────────────────┘
par └────────┘ └────────────────┘
pid ┴ ┴└───────────────┘
st ──────────────────────────────┘└─
497 { exact ⟨nil, perm.nil, nil_sublist _⟩ },
id └─┘ └──────┘ └─────────┘
src └────┘ └─┘└┘└──────┘└┘└─────────┘└──┘
typ └────┘ └─┘└┘└──────┘└┘└─────────┘└──┘
doc └────┘ └┘ └┘ └──┘
txt └────┘ └┘ └┘ └──┘
par └────┘ └┘ └┘ └──┘
pid ┴ └┘ └┘ └─┘┴
st ───┘└───────────────────────────────────┘└┘└
498 { cases forall_mem_cons.1 H with H₁ H₂,
id └─────────────┘ ┴
src └────┘└─────────────┘└─┘ └─────────┘
typ └────┘└─────────────┘└─┘┴└─────────┘
doc └────┘ └─┘ └─────────┘
txt └────┘ └─┘ └─────────┘
par └────┘ └─┘ └─────────┘
pid ┴ └─┘ └─────────┘
st ───────────────────────────────────────┘└─
499 simp at h,
src └───────┘
typ └───────┘
doc └───────┘
txt └───────┘
par └───────┘
pid ┴└──┘
st ────────────┘└─
500 exact cons_subperm_of_mem d h H₁ (IH H₂) }
id └─────────────────┘ ┴ ┴ └┘ └┘ └┘
src └────┘└─────────────────┘┴ ┴ ┴ ┴ ┴ └┘
typ └────┘└─────────────────┘┴┴┴┴┴└┘┴ └┘┴└┘└┘
doc └────┘ ┴ ┴ ┴ ┴ ┴ └┘
txt └────┘ ┴ ┴ ┴ ┴ ┴ └┘
par └────┘ ┴ ┴ ┴ ┴ ┴ └┘
pid ┴ ┴ ┴ ┴ ┴ ┴ ┴┴
st ────────────────────────────────────────────┘└─
501 end
st ──┘
502
503 theorem perm_ext {l₁ l₂ : list α} (d₁ : nodup l₁) (d₂ : nodup l₂) : l₁ ~ l₂ ↔ ∀a, a ∈ l₁ ↔ a ∈ l₂ :=
id └──┘ ┴ └───┘ └┘ └───┘ └┘ └┘ ┴ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘
src └──┘ └───┘ └───┘ ┴ ┴ ┴ ┴ ┴
typ └──┘ ┴ └───┘ └┘ └───┘ └┘ └┘ ┴ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ └┘
doc └───┘ └───┘ ┴
504 ⟨λ p a, mem_of_perm p, λ H, subperm.antisymm
id ┴ ┴ └─────────┘ ┴ ┴ └──────────────┘
src └─────────┘ └──────────────┘
typ ┴ ┴ └─────────┘ ┴ ┴ └──────────────┘
505 (subperm_of_subset_nodup d₁ (λ a, (H a).1))
id └─────────────────────┘ └┘ ┴ ┴ ┴ ┴
src └─────────────────────┘ ┴
typ └─────────────────────┘ └┘ ┴ ┴ ┴ ┴
506 (subperm_of_subset_nodup d₂ (λ a, (H a).2))⟩
id └─────────────────────┘ └┘ ┴ ┴ ┴ ┴
src └─────────────────────┘ ┴
typ └─────────────────────┘ └┘ ┴ ┴ ┴ ┴
507
508 theorem perm_ext_sublist_nodup {l₁ l₂ l : list α} (d : nodup l)
id └──┘ ┴ └───┘ ┴
src └──┘ └───┘
typ └──┘ ┴ └───┘ ┴
doc └───┘
509 (s₁ : l₁ <+ l) (s₂ : l₂ <+ l) : l₁ ~ l₂ ↔ l₁ = l₂ :=
id └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘
src └┘ └┘ ┴ ┴ ┴
typ └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘
doc ┴
510 ⟨λ h, begin
id ┴
typ ┴
st └─────
511 induction s₂ with l₂ l a s₂ IH l₂ l a s₂ IH generalizing l₁,
id └┘
src └────────┘ └─────────────────────────────────────────────┘
typ └────────┘└┘└─────────────────────────────────────────────┘
doc └────────┘ └─────────────────────────────────────────────┘
txt └────────┘ └─────────────────────────────────────────────┘
par └────────┘ └─────────────────────────────────────────────┘
pid ┴ ┴└────────────────────────────┘└──────────────┘
st ────────────────────────────────────────────────────────────┘└─
512 { exact eq_nil_of_perm_nil h.symm },
id └────────────────┘ └────┘
src └────┘└────────────────┘┴└────┘┴
typ └────┘└────────────────┘┴└────┘┴
doc └────┘ ┴ ┴
txt └────┘ ┴ ┴
par └────┘ ┴ ┴
pid ┴ ┴ ┴
st ───┘└──────────────────────────────┘└┘└
513 { simp at d,
src └───────┘
typ └───────┘
doc └───────┘
txt └───────┘
par └───────┘
pid ┴└──┘
st ───┘└───────┘└─
514 cases s₁ with _ _ _ s₁ l₁ _ _ s₁,
id └┘
src └────┘ └──────────────────────┘
typ └────┘└┘└──────────────────────┘
doc └────┘ └──────────────────────┘
txt └────┘ └──────────────────────┘
par └────┘ └──────────────────────┘
pid ┴ └──────────────────────┘
st ───────────────────────────────────┘└─
515 { exact IH d.2 s₁ h },
id └┘ ┴ └┘ ┴
src └────┘ ┴ └─┘ ┴ ┴
typ └────┘└┘┴┴└─┘└┘┴┴┴
doc └────┘ ┴ └─┘ ┴ ┴
txt └────┘ ┴ └─┘ ┴ ┴
par └────┘ ┴ └─┘ ┴ ┴
pid ┴ ┴ └─┘ ┴ ┴
st ─────┘└────────────────┘└┘└
516 { apply d.1.elim,
id ┴
src └────┘ └─────┘
typ └────┘┴└─────┘
doc └────┘ └─────┘
txt └────┘ └─────┘
par └────┘ └─────┘
pid ┴ └────┘┴
st ───────────────────┘└─
517 exact subset_of_subperm ⟨_, h.symm, s₂⟩ (mem_cons_self _ _) } },
id └───────────────┘ └────┘ └┘ └───────────┘
src └────┘└───────────────┘┴ └─┘└────┘└┘ └┘ └───────────┘└────┘
typ └────┘└───────────────┘┴ └─┘└────┘└┘└┘└┘ └───────────┘└────┘
doc └────┘ ┴ └─┘ └┘ └┘ └────┘
txt └────┘ ┴ └─┘ └┘ └┘ └────┘
par └────┘ ┴ └─┘ └┘ └┘ └────┘
pid ┴ ┴ └─┘ └┘ └┘ └───┘┴
st ─────────────────────────────────────────────────────────────────┘└──┘└
518 { simp at d,
src └───────┘
typ └───────┘
doc └───────┘
txt └───────┘
par └───────┘
pid ┴└──┘
st ────────────┘└─
519 cases s₁ with _ _ _ s₁ l₁ _ _ s₁,
id └┘
src └────┘ └──────────────────────┘
typ └────┘└┘└──────────────────────┘
doc └────┘ └──────────────────────┘
txt └────┘ └──────────────────────┘
par └────┘ └──────────────────────┘
pid ┴ └──────────────────────┘
st ───────────────────────────────────┘└─
520 { apply d.1.elim,
id ┴
src └────┘ └─────┘
typ └────┘┴└─────┘
doc └────┘ └─────┘
txt └────┘ └─────┘
par └────┘ └─────┘
pid ┴ └────┘┴
st ─────┘└────────────┘└─
521 exact subset_of_subperm ⟨_, h, s₁⟩ (mem_cons_self _ _) },
id └───────────────┘ ┴ └┘ └───────────┘
src └────┘└───────────────┘┴ └─┘ └┘ └┘ └───────────┘└────┘
typ └────┘└───────────────┘┴ └─┘┴└┘└┘└┘ └───────────┘└────┘
doc └────┘ ┴ └─┘ └┘ └┘ └────┘
txt └────┘ ┴ └─┘ └┘ └┘ └────┘
par └────┘ ┴ └─┘ └┘ └┘ └────┘
pid ┴ ┴ └─┘ └┘ └┘ └───┘┴
st ────────────────────────────────────────────────────────────┘└┘└
522 { rw IH d.2 s₁ (perm_cons_inv h) } }
id └┘ ┴ └┘ └───────────┘ ┴
src └─┘ ┴ └─┘ ┴ └───────────┘┴ └┘
typ └─┘└┘┴┴└─┘└┘┴ └───────────┘┴┴└┘
doc └─┘ ┴ └─┘ ┴ ┴ └┘
txt └─┘ ┴ └─┘ ┴ ┴ └┘
par └─┘ ┴ └─┘ ┴ ┴ └┘
pid ┴ ┴ └─┘ ┴ ┴ ┴┴
st ────────────────────────────────────┘└───
523 end, λ h, by rw h⟩
id ┴ ┴
src └─┘
typ ┴ └─┘┴
doc └─┘
txt └─┘
par └─┘
pid ┴
st ──┘ └───┘
524
525 section
526 variable [decidable_eq α]
id └──────────┘
src └──────────┘
typ └──────────┘
527
528 -- attribute [congr]
529 theorem erase_perm_erase (a : α) {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id ┴ └──┘ ┴ └┘ ┴ └┘
src └──┘ ┴
typ ┴ └──┘ ┴ └┘ ┴ └┘
doc ┴
530 l₁.erase a ~ l₂.erase a :=
id └┘└────┘ ┴ ┴ └┘└────┘ ┴
src └────┘ ┴ └────┘
typ └┘└────┘ ┴ ┴ └┘└────┘ ┴
doc ┴
531 if h₁ : a ∈ l₁ then
id └┘ ┴ ┴ └┘
src └┘ ┴
typ └┘ ┴ ┴ └┘
532 have h₂ : a ∈ l₂, from perm_subset p h₁,
id ┴ ┴ └┘ └─────────┘ ┴ └┘
src ┴ └─────────┘
typ ┴ ┴ └┘ └─────────┘ ┴ └┘
533 perm_cons_inv $ trans (perm_erase h₁).symm $ trans p (perm_erase h₂)
id └───────────┘ └───┘ └────────┘ └┘ └──┘ └───┘ ┴ └────────┘ └┘
src └───────────┘ └───┘ └────────┘ └──┘ └───┘ └────────┘
typ └───────────┘ └───┘ └────────┘ └┘ └──┘ └───┘ ┴ └────────┘ └┘
534 else
535 have h₂ : a ∉ l₂, from mt (mem_of_perm p).2 h₁,
id └──┘ ┴ ┴ └┘ └┘ └─────────┘ ┴ ┴ └┘
src └──┘ ┴ └┘ └─────────┘ ┴
typ └──┘ ┴ ┴ └┘ └┘ └─────────┘ ┴ ┴ └┘
536 by rw [erase_of_not_mem h₁, erase_of_not_mem h₂]; exact p
id └──────────────┘ └┘ └──────────────┘ └┘ ┴
src └──┘└──────────────┘┴ └┘└──────────────┘┴ ┴ └────┘ └
typ └──┘└──────────────┘┴└┘└┘└──────────────┘┴└┘┴ └────┘┴└
doc └──┘ ┴ └┘ ┴ ┴ └────┘ └
txt └──┘ ┴ └┘ ┴ ┴ └────┘ └
par └──┘ ┴ └┘ ┴ ┴ └────┘ └
pid └┘ ┴ └┘ ┴ ┴ ┴ └
st └──────────────────────┘└───────────────────┘┴└─────────
537
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
538 theorem erase_subperm (a : α) (l : list α) : l.erase a <+~ l :=
id ┴ └──┘ ┴ ┴└────┘ ┴ └─┘ ┴
src └──┘ └────┘ └─┘
typ ┴ └──┘ ┴ ┴└────┘ ┴ └─┘ ┴
doc └─┘
539 ⟨l.erase a, perm.refl _, erase_sublist _ _⟩
id ┴└────┘ ┴ └───────┘ └───────────┘
src └────┘ └───────┘ └───────────┘
typ ┴└────┘ ┴ └───────┘ └───────────┘
540
541 theorem erase_subperm_erase {l₁ l₂ : list α} (a : α) (h : l₁ <+~ l₂) : l₁.erase a <+~ l₂.erase a :=
id └──┘ ┴ ┴ └┘ └─┘ └┘ └┘└────┘ ┴ └─┘ └┘└────┘ ┴
src └──┘ └─┘ └────┘ └─┘ └────┘
typ └──┘ ┴ ┴ └┘ └─┘ └┘ └┘└────┘ ┴ └─┘ └┘└────┘ ┴
doc └─┘ └─┘
542 let ⟨l, hp, hs⟩ := h in ⟨l.erase a, erase_perm_erase _ hp, erase_sublist_erase _ hs⟩
id └─┘ ┴ └┘ └┘ ┴ └────┘ ┴ └──────────────┘ └─────────────────┘
src └────┘ └──────────────┘ └─────────────────┘
typ └─┘ ┴ └┘ └┘ ┴ └────┘ ┴ └──────────────┘ └─────────────────┘
543
544 theorem perm_diff_left {l₁ l₂ : list α} (t : list α) (h : l₁ ~ l₂) : l₁.diff t ~ l₂.diff t :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘└───┘ ┴ ┴ └┘└───┘ ┴
src └──┘ └──┘ ┴ └───┘ ┴ └───┘
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘└───┘ ┴ ┴ └┘└───┘ ┴
doc ┴ ┴
545 by induction t generalizing l₁ l₂ h; simp [*, erase_perm_erase]
id ┴ └──────────────┘
src └────────┘ └───────────────────┘ └───────┘└──────────────┘└─
typ └────────┘┴└───────────────────┘ └───────┘└──────────────┘└─
doc └────────┘ └───────────────────┘ └───────┘ └─
txt └────────┘ └───────────────────┘ └───────┘ └─
par └────────┘ └───────────────────┘ └───────┘ └─
pid ┴ ┴└──────────────────┘ ┴└──┘ ┴└
st └─────────────────────────────────────────────────────────────
546
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
547 theorem perm_diff_right (l : list α) {t₁ t₂ : list α} (h : t₁ ~ t₂) : l.diff t₁ = l.diff t₂ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴└───┘ └┘ ┴ ┴└───┘ └┘
src └──┘ └──┘ ┴ └───┘ ┴ └───┘
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴└───┘ └┘ ┴ ┴└───┘ └┘
doc ┴
548 by induction h generalizing l; simp [*, erase_perm_erase, erase_comm]
id ┴ └──────────────┘ └────────┘
src └────────┘ └─────────────┘ └───────┘└──────────────┘└┘└────────┘└─
typ └────────┘┴└─────────────┘ └───────┘└──────────────┘└┘└────────┘└─
doc └────────┘ └─────────────┘ └───────┘ └┘ └─
txt └────────┘ └─────────────┘ └───────┘ └┘ └─
par └────────┘ └─────────────┘ └───────┘ └┘ └─
pid ┴ ┴└────────────┘ ┴└──┘ └┘ ┴└
st └───────────────────────────────────────────────────────────────────
549 <|> exact (ih_1 _).trans (ih_2 _)
src ─┘ └────┘ └────────┘ └───
typ ─┘ └────┘ └────────┘ └───
doc ─┘ └────┘ └────────┘ └───
txt ─┘ └────┘ └────────┘ └───
par ─┘ └────┘ └────────┘ └───
pid ─┘ ┴ └────────┘ └─┘└
st ────────────────────────────────────
550
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
551 theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : list α}, (a :: l₁).diff l₂ <+~ a :: l₁.diff l₂
id ┴ ┴ └──┘ ┴ ┴ └┘ └┘ └──┘ └┘ └─┘ ┴ └┘ └┘└───┘ └┘
src └──┘ └┘ └──┘ └─┘ └┘ └───┘
typ ┴ ┴ └──┘ ┴ ┴ └┘ └┘ └──┘ └┘ └─┘ ┴ └┘ └┘└───┘ └┘
doc └─┘
552 | l₁ [] := ⟨a::l₁, by simp⟩
id └┘ └┘ ┴└┘
src └┘ └┘ └──┘
typ └┘ └┘ ┴└┘ └──┘
doc └──┘
txt └──┘
par └──┘
st └───┘
553 | l₁ (b::l₂) :=
id └┘
src └┘
typ └┘
554 begin
st └─────
555 repeat {rw diff_cons},
id └───────┘
src └──────┘└─┘└───────┘┴
typ └──────┘└─┘└───────┘┴
doc └──────┘└─┘ ┴
txt └──────┘└─┘ ┴
par └──────┘└─┘ ┴
pid └───┘ ┴
st ─────────────────────┘└┘└
556 by_cases heq : a = b,
id ┴ ┴ ┴
src └───────┘ └─┘ ┴┴┴
typ └───────┘ └─┘┴┴┴┴┴
doc └───────┘ └─┘ ┴ ┴
txt └───────┘ └─┘ ┴ ┴
par └───────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴
st ─────────────────────┘└─
557 { by_cases b ∈ l₁,
id ┴ ┴ └┘
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴└┘
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ───┘└─────────────┘└─
558 { rw perm.subperm_right, apply subperm_cons_diff,
id └────────────────┘
src └─┘└────────────────┘ └────┘
typ └─┘└────────────────┘ └────┘
doc └─┘ └────┘
txt └─┘ └────┘
par └─┘ └────┘
pid ┴ ┴
st ─────┘└───────────────────┘└───────────────────────┘└─
559 simp [perm_diff_left, heq, perm_erase h] },
id └────────────┘ └─┘ └────────┘ ┴
src └────┘└────────────┘└┘└─┘└┘└────────┘┴ └┘
typ └────┘└────────────┘└┘└─┘└┘└────────┘┴┴└┘
doc └────┘ └┘ └┘ ┴ └┘
txt └────┘ └┘ └┘ ┴ └┘
par └────┘ └┘ └┘ ┴ └┘
pid ┴┴ └┘ └┘ ┴ ┴┴
st ──────────────────────────────────────────────┘└┘└
560 { simp [subperm_of_sublist, sublist.cons, h, heq] } },
id └────────────────┘ └──────────┘ ┴ └─┘
src └────┘└────────────────┘└┘└──────────┘└┘ └┘└─┘└┘
typ └────┘└────────────────┘└┘└──────────┘└┘┴└┘└─┘└┘
doc └────┘ └┘ └┘ └┘ └┘
txt └────┘ └┘ └┘ └┘ └┘
par └────┘ └┘ └┘ └┘ └┘
pid ┴┴ └┘ └┘ └┘ ┴┴
st ─────────────────────────────────────────────────────┘└──┘└
561 { simp [heq, subperm_cons_diff] }
id └─┘
src └────┘└─┘└┘ └┘
typ └────┘└─┘└┘└───────────────┘└┘
doc └────┘ └┘ └┘
txt └────┘ └┘ └┘
par └────┘ └┘ └┘
pid ┴┴ └┘ ┴┴
st ─────────────────────────────────┘└─
562 end
st ──┘
563
564 theorem subset_cons_diff {a : α} {l₁ l₂ : list α} : (a :: l₁).diff l₂ ⊆ a :: l₁.diff l₂ :=
id ┴ └──┘ ┴ ┴ └┘ └┘ └──┘ └┘ ┴ ┴ └┘ └┘└───┘ └┘
src └──┘ └┘ └──┘ ┴ └┘ └───┘
typ ┴ └──┘ ┴ ┴ └┘ └┘ └──┘ └┘ ┴ ┴ └┘ └┘└───┘ └┘
565 subset_of_subperm subperm_cons_diff
id └───────────────┘ └───────────────┘
src └───────────────┘ └───────────────┘
typ └───────────────┘ └───────────────┘
566
567 theorem perm_bag_inter_left {l₁ l₂ : list α} (t : list α) (h : l₁ ~ l₂) : l₁.bag_inter t ~ l₂.bag_inter t :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘└────────┘ ┴ ┴ └┘└────────┘ ┴
src └──┘ └──┘ ┴ └────────┘ ┴ └────────┘
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘└────────┘ ┴ ┴ └┘└────────┘ ┴
doc ┴ ┴
568 begin
st └─────
569 induction h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t, {simp},
id ┴
src └────────┘ └──────────────────────────────────────────────────────┘ └──┘
typ └────────┘┴└──────────────────────────────────────────────────────┘ └──┘
doc └────────┘ └──────────────────────────────────────────────────────┘ └──┘
txt └────────┘ └──────────────────────────────────────────────────────┘ └──┘
par └────────┘ └──────────────────────────────────────────────────────┘ └──┘
pid ┴ ┴└──────────────────────────────────────┘└─────────────┘
st ────────────────────────────────────────────────────────────────────┘└─────┘└┘└
570 { by_cases x ∈ t; simp [*, skip] },
id ┴ ┴ ┴ └──┘
src └───────┘ ┴┴┴ └───────┘└──┘└┘
typ └───────┘┴┴┴┴┴ └───────┘└──┘└┘
doc └───────┘ ┴ ┴ └───────┘ └┘
txt └───────┘ ┴ ┴ └───────┘ └┘
par └───────┘ ┴ ┴ └───────┘ └┘
pid ┴ ┴ ┴ ┴└──┘ ┴┴
st ───┘└─────────────────────────────┘└┘└
571 { by_cases x = y, {simp [h]},
id ┴ ┴ ┴ ┴
src └───────┘ ┴┴┴ └────┘ ┴
typ └───────┘┴┴┴┴┴ └────┘┴┴
doc └───────┘ ┴ ┴ └────┘ ┴
txt └───────┘ ┴ ┴ └────┘ ┴
par └───────┘ ┴ ┴ └────┘ ┴
pid ┴ ┴ ┴ ┴┴ ┴
st ───┘└────────────┘└─────────┘└┘└
572 by_cases xt : x ∈ t; by_cases yt : y ∈ t,
id ┴ ┴ ┴ ┴
src └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴
typ └───────┘ └─┘┴┴ ┴┴ └───────┘ └─┘┴┴ ┴┴
doc └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴
txt └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴
par └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴
pid ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴
st ───────────────────────────────────────────┘└─
573 { simp [xt, yt, mem_erase_of_ne h, mem_erase_of_ne (ne.symm h), erase_comm, swap] },
id └┘ └┘ └─────────────┘ ┴ └─────────────┘ └─────┘ ┴ └────────┘ └──┘
src └────┘ └┘ └┘└─────────────┘┴ └┘└─────────────┘┴ └─────┘┴ └─┘└────────┘└┘└──┘└┘
typ └────┘└┘└┘└┘└┘└─────────────┘┴┴└┘└─────────────┘┴ └─────┘┴┴└─┘└────────┘└┘└──┘└┘
doc └────┘ └┘ └┘ ┴ └┘ ┴ ┴ └─┘ └┘ └┘
txt └────┘ └┘ └┘ ┴ └┘ ┴ ┴ └─┘ └┘ └┘
par └────┘ └┘ └┘ ┴ └┘ ┴ ┴ └─┘ └┘ └┘
pid ┴┴ └┘ └┘ ┴ └┘ ┴ ┴ └─┘ └┘ ┴┴
st ─────┘└──────────────────────────────────────────────────────────────────────────────┘└┘└
574 { simp [xt, yt, mt mem_of_mem_erase, skip] },
id └┘ └┘ └┘ └──────────────┘ └──┘
src └────┘ └┘ └┘└┘┴└──────────────┘└┘└──┘└┘
typ └────┘└┘└┘└┘└┘└┘┴└──────────────┘└┘└──┘└┘
doc └────┘ └┘ └┘ ┴ └┘ └┘
txt └────┘ └┘ └┘ ┴ └┘ └┘
par └────┘ └┘ └┘ ┴ └┘ └┘
pid ┴┴ └┘ └┘ ┴ └┘ ┴┴
st ─────┘└───────────────────────────────────────┘└┘└
575 { simp [xt, yt, mt mem_of_mem_erase, skip] },
id └┘ └┘ └┘ └──────────────┘ └──┘
src └────┘ └┘ └┘└┘┴└──────────────┘└┘└──┘└┘
typ └────┘└┘└┘└┘└┘└┘┴└──────────────┘└┘└──┘└┘
doc └────┘ └┘ └┘ ┴ └┘ └┘
txt └────┘ └┘ └┘ ┴ └┘ └┘
par └────┘ └┘ └┘ ┴ └┘ └┘
pid ┴┴ └┘ └┘ ┴ └┘ ┴┴
st ─────┘└───────────────────────────────────────┘└┘└
576 { simp [xt, yt] } },
id └┘ └┘
src └────┘ └┘ └┘
typ └────┘└┘└┘└┘└┘
doc └────┘ └┘ └┘
txt └────┘ └┘ └┘
par └────┘ └┘ └┘
pid ┴┴ └┘ ┴┴
st ───────────────────┘└──┘└
577 { exact (ih_1 _).trans (ih_2 _) }
id └──┘ └──┘
src └────┘ └────────┘ └──┘
typ └────┘ └──┘└────────┘ └──┘└──┘
doc └────┘ └────────┘ └──┘
txt └────┘ └────────┘ └──┘
par └────┘ └────────┘ └──┘
pid ┴ └────────┘ └─┘┴
st ─────────────────────────────────┘└─
578 end
st ──┘
579
580 theorem perm_bag_inter_right (l : list α) {t₁ t₂ : list α} (p : t₁ ~ t₂) : l.bag_inter t₁ = l.bag_inter t₂ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴└────────┘ └┘ ┴ ┴└────────┘ └┘
src └──┘ └──┘ ┴ └────────┘ ┴ └────────┘
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴└────────┘ └┘ ┴ ┴└────────┘ └┘
doc ┴
581 begin
st └─────
582 induction l with a l IH generalizing t₁ t₂ p, {simp},
id ┴
src └────────┘ └───────────────────────────────┘ └──┘
typ └────────┘┴└───────────────────────────────┘ └──┘
doc └────────┘ └───────────────────────────────┘ └──┘
txt └────────┘ └───────────────────────────────┘ └──┘
par └────────┘ └───────────────────────────────┘ └──┘
pid ┴ ┴└─────────┘└───────────────────┘
st ─────────────────────────────────────────────┘└─────┘└┘└
583 by_cases a ∈ t₁,
id ┴ ┴ └┘
src └───────┘ ┴┴┴
typ └───────┘┴┴┴┴└┘
doc └───────┘ ┴ ┴
txt └───────┘ ┴ ┴
par └───────┘ ┴ ┴
pid ┴ ┴ ┴
st ────────────────┘└─
584 { simp [h, (mem_of_perm p).1 h, IH (erase_perm_erase _ p)] },
id ┴ └─────────┘ ┴ ┴ └┘ └──────────────┘ ┴
src └────┘ └┘ └─────────┘┴ └──┘ └┘ ┴ └──────────────┘└─┘ └─┘
typ └────┘┴└┘ └─────────┘┴┴└──┘┴└┘└┘┴ └──────────────┘└─┘┴└─┘
doc └────┘ └┘ ┴ └──┘ └┘ ┴ └─┘ └─┘
txt └────┘ └┘ ┴ └──┘ └┘ ┴ └─┘ └─┘
par └────┘ └┘ ┴ └──┘ └┘ ┴ └─┘ └─┘
pid ┴┴ └┘ ┴ └──┘ └┘ ┴ └─┘ └┘┴
st ───┘└───────────────────────────────────────────────────────┘└┘└
585 { simp [h, mt (mem_of_perm p).2 h, IH p] }
id ┴ └┘ └─────────┘ ┴ ┴ └┘ ┴
src └────┘ └┘└┘┴ └─────────┘┴ └──┘ └┘ ┴ └┘
typ └────┘┴└┘└┘┴ └─────────┘┴┴└──┘┴└┘└┘┴┴└┘
doc └────┘ └┘ ┴ ┴ └──┘ └┘ ┴ └┘
txt └────┘ └┘ ┴ ┴ └──┘ └┘ ┴ └┘
par └────┘ └┘ ┴ ┴ └──┘ └┘ ┴ └┘
pid ┴┴ └┘ ┴ ┴ └──┘ └┘ ┴ ┴┴
st ──────────────────────────────────────────┘└─
586 end
st ──┘
587
588 theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : list α} : a::l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.erase a :=
id ┴ └──┘ ┴ ┴└┘└┘ ┴ └┘ ┴ ┴ ┴ └┘ ┴ └┘ ┴ └┘└────┘ ┴
src └──┘ └┘ ┴ ┴ ┴ ┴ ┴ └────┘
typ ┴ └──┘ ┴ ┴└┘└┘ ┴ └┘ ┴ ┴ ┴ └┘ ┴ └┘ ┴ └┘└────┘ ┴
doc ┴ ┴
589 ⟨λ h, have a ∈ l₂, from perm_subset h (mem_cons_self a l₁),
id ┴ ┴ ┴ └┘ └─────────┘ ┴ └───────────┘ ┴ └┘
src ┴ └─────────┘ └───────────┘
typ ┴ ┴ ┴ └┘ └─────────┘ ┴ └───────────┘ ┴ └┘
590 ⟨this, perm_cons_inv $ h.trans $ perm_erase this⟩,
id └──┘ └───────────┘ ┴└────┘ └────────┘ └──┘
src └───────────┘ └────┘ └────────┘
typ └──┘ └───────────┘ ┴└────┘ └────────┘ └──┘
591 λ ⟨m, h⟩, trans (skip a h) (perm_erase m).symm⟩
id ┴┴ ┴ └───┘ └──┘ ┴ └────────┘ └──┘
src └───┘ └──┘ └────────┘ └──┘
typ ┴┴ ┴ └───┘ └──┘ ┴ └────────┘ └──┘
592
593 theorem perm_iff_count {l₁ l₂ : list α} : l₁ ~ l₂ ↔ ∀ a, count a l₁ = count a l₂ :=
id └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └───┘ ┴ └┘ ┴ └───┘ ┴ └┘
src └──┘ ┴ ┴ └───┘ ┴ └───┘
typ └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └───┘ ┴ └┘ ┴ └───┘ ┴ └┘
doc ┴ └───┘ └───┘
594 ⟨perm_count, λ H, begin
id └────────┘ ┴
src └────────┘
typ └────────┘ ┴
st └─────
595 induction l₁ with a l₁ IH generalizing l₂,
id └┘
src └────────┘ └───────────────────────────┘
typ └────────┘└┘└───────────────────────────┘
doc └────────┘ └───────────────────────────┘
txt └────────┘ └───────────────────────────┘
par └────────┘ └───────────────────────────┘
pid ┴ ┴└──────────┘└──────────────┘
st ──────────────────────────────────────────┘└─
596 { cases l₂ with b l₂, {refl},
id └┘
src └────┘ └────────┘ └──┘
typ └────┘└┘└────────┘ └──┘
doc └────┘ └────────┘ └──┘
txt └────┘ └────────┘ └──┘
par └────┘ └────────┘ └──┘
pid ┴ └────────┘
st ───┘└────────────────┘└─────┘└┘└
597 specialize H b, simp at H, contradiction },
id ┴ ┴
src └─────────┘ ┴ └───────┘ └────────────┘
typ └─────────┘┴┴┴ └───────┘ └────────────┘
doc └─────────┘ ┴ └───────┘ └────────────┘
txt └─────────┘ ┴ └───────┘ └────────────┘
par └─────────┘ ┴ └───────┘ └────────────┘
pid ┴ ┴ ┴└──┘ ┴
st ─────────────────┘└─────────┘└──────────────┘└┘└
598 { have : a ∈ l₂ := count_pos.1 (by rw ← H; simp; apply nat.succ_pos),
id ┴ ┴ └┘ └───────┘ ┴
src └─────┘ ┴┴┴ └──┘└───────┘└─┘ ┴└───┘ └┘└──┘└┘└────┘ ┴
typ └─────┘┴┴┴┴└┘└──┘└───────┘└─┘ ┴└───┘┴└┘└──┘└┘└────┘ ┴
doc └─────┘ ┴ ┴ └──┘ └─┘ ┴└───┘ └┘└──┘└┘└────┘ ┴
txt └─────┘ ┴ ┴ └──┘ └─┘ ┴└───┘ └┘└──┘└┘└────┘ ┴
par └─────┘ ┴ ┴ └──┘ └─┘ ┴└───┘ └┘└──┘└┘└────┘ ┴
pid └───┘└┘ ┴ ┴ └──┘ └─┘ └────┘ └────────────┘ ┴
st ───────────────────────────────────┘└───────────────────────────────┘┴└─
599 refine trans (skip a $ IH $ λ b, _) (perm_erase this).symm,
id └───┘ └──┘ ┴ └┘ └────────┘ └──┘
src └─────┘└───┘┴ └──┘┴ ┴ ┴ ┴ ┴ └─────┘ └────────┘┴ └────┘
typ └─────┘└───┘┴ └──┘┴┴┴ ┴└┘┴ ┴ └─────┘ └────────┘┴└──┘└────┘
doc └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ └────┘
txt └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ └────┘
par └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ └────┘
pid ┴ ┴ ┴ ┴ ┴ ┴ ┴ └─────┘ ┴ └───┘┴
st ─────────────────────────────────────────────────────────────┘└─
600 specialize H b,
id ┴ ┴
src └─────────┘ ┴
typ └─────────┘┴┴┴
doc └─────────┘ ┴
txt └─────────┘ ┴
par └─────────┘ ┴
pid ┴ ┴
st ─────────────────┘└─
601 rw perm_count (perm_erase this) at H,
id └────────┘ └────────┘ └──┘
src └─┘└────────┘┴ └────────┘┴ └────┘
typ └─┘└────────┘┴ └────────┘┴└──┘└────┘
doc └─┘ ┴ ┴ └────┘
txt └─┘ ┴ ┴ └────┘
par └─┘ ┴ ┴ └────┘
pid ┴ ┴ ┴ ┴└───┘
st ───────────────────────────────────────┘└─
602 by_cases b = a; simp [h] at H ⊢; assumption }
id ┴ ┴ ┴ ┴
src └───────┘ ┴┴┴ └────┘ └──────┘ └─────────┘
typ └───────┘┴┴┴┴┴ └────┘┴└──────┘ └─────────┘
doc └───────┘ ┴ ┴ └────┘ └──────┘ └─────────┘
txt └───────┘ ┴ ┴ └────┘ └──────┘ └─────────┘
par └───────┘ ┴ ┴ └────┘ └──────┘ └─────────┘
pid ┴ ┴ ┴ ┴┴ ┴┴└────┘ ┴
st ───────────────────────────────────────────────┘└─
603 end⟩
st ──┘
604
605 instance decidable_perm : ∀ (l₁ l₂ : list α), decidable (l₁ ~ l₂)
id ┴ └──┘ ┴ └───────┘ └┘ ┴ └┘
src └──┘ └───────┘ ┴
typ ┴ └──┘ ┴ └───────┘ └┘ ┴ └┘
doc ┴
606 | [] [] := is_true $ perm.refl _
id └┘ └┘ └─────┘ └───────┘
src └┘ └┘ └─────┘ └───────┘
typ └┘ └┘ └─────┘ └───────┘
607 | [] (b::l₂) := is_false $ λ h, by have := eq_nil_of_perm_nil h; contradiction
id └┘ └┘ └──────┘ ┴ └────────────────┘ ┴
src └┘ └┘ └──────┘ └──────┘└────────────────┘┴ └────────────┘
typ └┘ └┘ └──────┘ ┴ └──────┘└────────────────┘┴┴ └────────────┘
doc └──────┘ ┴ └────────────┘
txt └──────┘ ┴ └────────────┘
par └──────┘ ┴ └────────────┘
pid └───┘└─┘ ┴ ┴
st └───────────────────────────────────────────┘
608 | (a::l₁) l₂ := by haveI := decidable_perm l₁ (l₂.erase a);
id └┘ └────────────┘ └┘ └──────┘ ┴
src └┘ └───────┘ ┴ ┴ └──────┘┴ ┴
typ └┘ └───────┘└────────────┘┴└┘┴ └──────┘┴┴┴
doc └───────┘ ┴ ┴ ┴ ┴
txt └───────┘ ┴ ┴ ┴ ┴
par └───────┘ ┴ ┴ ┴ ┴
pid ┴└─┘ ┴ ┴ ┴ ┴
st └─────────────────────────────────────────
609 exact decidable_of_iff' _ cons_perm_iff_perm_erase
id └───────────────┘ └──────────────────────┘
src └────┘└───────────────┘└─┘└──────────────────────┘└
typ └────┘└───────────────┘└─┘└──────────────────────┘└
doc └────┘ └─┘ └
txt └────┘ └─┘ └
par └────┘ └─┘ └
pid ┴ └─┘ └
st ───────────────────────────────────────────────────────────────────────────
610
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
611 -- @[congr]
src ───────────┘
typ ───────────┘
doc ───────────┘
txt ───────────┘
par ───────────┘
pid ───────────┘
st ───────────┘
612 theorem perm_erase_dup_of_perm {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id └──┘ ┴ └┘ ┴ └┘
src └──┘ ┴
typ └──┘ ┴ └┘ ┴ └┘
doc ┴
613 erase_dup l₁ ~ erase_dup l₂ :=
id └───────┘ └┘ ┴ └───────┘ └┘
src └───────┘ ┴ └───────┘
typ └───────┘ └┘ ┴ └───────┘ └┘
doc └───────┘ ┴ └───────┘
614 perm_iff_count.2 $ λ a,
id └────────────┘┴ ┴
src └────────────┘┴
typ └────────────┘┴ ┴
615 if h : a ∈ l₁
id └┘ ┴ ┴ └┘
src └┘ ┴
typ └┘ ┴ ┴ └┘
616 then by simp [nodup_erase_dup, h, perm_subset p h]
id └─────────────┘ ┴ └─────────┘ ┴ ┴
src └────┘└─────────────┘└┘ └┘└─────────┘┴ ┴ └┘
typ └────┘└─────────────┘└┘┴└┘└─────────┘┴┴┴┴└┘
doc └────┘ └┘ └┘ ┴ ┴ └┘
txt └────┘ └┘ └┘ ┴ ┴ └┘
par └────┘ └┘ └┘ ┴ ┴ └┘
pid ┴┴ └┘ └┘ ┴ ┴ ┴┴
st └──────────────────────────────────────────┘
617 else by simp [h, mt (mem_of_perm p).2 h]
id ┴ └┘ └─────────┘ ┴ ┴
src └────┘ └┘└┘┴ └─────────┘┴ └──┘ └─
typ └────┘┴└┘└┘┴ └─────────┘┴┴└──┘┴└─
doc └────┘ └┘ ┴ ┴ └──┘ └─
txt └────┘ └┘ ┴ ┴ └──┘ └─
par └────┘ └┘ ┴ ┴ └──┘ └─
pid ┴┴ └┘ ┴ ┴ └──┘ ┴└
st └─────────────────────────────────
618
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
619 -- attribute [congr]
src ────────────────────┘
typ ────────────────────┘
doc ────────────────────┘
txt ────────────────────┘
par ────────────────────┘
pid ────────────────────┘
st ────────────────────┘
620 theorem perm_insert (a : α)
id ┴
typ ┴
621 {l₁ l₂ : list α} (p : l₁ ~ l₂) : insert a l₁ ~ insert a l₂ :=
id └──┘ ┴ └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
src └──┘ ┴ └────┘ ┴ └────┘
typ └──┘ ┴ └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
doc ┴ ┴
622 if h : a ∈ l₁
id └┘ ┴ ┴ └┘
src └┘ ┴
typ └┘ ┴ ┴ └┘
623 then by simpa [h, perm_subset p h] using p
id ┴ └─────────┘ ┴ ┴ ┴
src └─────┘ └┘└─────────┘┴ ┴ └──────┘ ┴
typ └─────┘┴└┘└─────────┘┴┴┴┴└──────┘┴┴
doc └─────┘ └┘ ┴ ┴ └──────┘ ┴
txt └─────┘ └┘ ┴ ┴ └──────┘ ┴
par └─────┘ └┘ ┴ ┴ └──────┘ ┴
pid ┴┴ └┘ ┴ ┴ ┴┴└────┘ ┴
st └──────────────────────────────────┘
624 else by simpa [h, mt (mem_of_perm p).2 h] using skip a p
id ┴ └┘ └─────────┘ ┴ ┴ └──┘ ┴ ┴
src └─────┘ └┘└┘┴ └─────────┘┴ └──┘ └──────┘└──┘┴ ┴ └
typ └─────┘┴└┘└┘┴ └─────────┘┴┴└──┘┴└──────┘└──┘┴┴┴┴└
doc └─────┘ └┘ ┴ ┴ └──┘ └──────┘ ┴ ┴ └
txt └─────┘ └┘ ┴ ┴ └──┘ └──────┘ ┴ ┴ └
par └─────┘ └┘ ┴ ┴ └──┘ └──────┘ ┴ ┴ └
pid ┴┴ └┘ ┴ ┴ └──┘ ┴┴└────┘ ┴ ┴ └
st └─────────────────────────────────────────────────
625
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
626 theorem perm_insert_swap (x y : α) (l : list α) :
id ┴ └──┘ ┴
src └──┘
typ ┴ └──┘ ┴
627 insert x (insert y l) ~ insert y (insert x l) :=
id └────┘ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ └────┘ ┴ ┴
src └────┘ └────┘ ┴ └────┘ └────┘
typ └────┘ ┴ └────┘ ┴ ┴ ┴ └────┘ ┴ └────┘ ┴ ┴
doc ┴
628 begin
st └─────
629 by_cases xl : x ∈ l; by_cases yl : y ∈ l; simp [xl, yl],
id ┴ ┴ ┴ ┴ ┴ └┘ └┘
src └───────┘ └─┘ ┴┴┴ └───────┘ └─┘ ┴ ┴ └────┘ └┘ ┴
typ └───────┘ └─┘┴┴┴┴┴ └───────┘ └─┘┴┴ ┴┴ └────┘└┘└┘└┘┴
doc └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴ └────┘ └┘ ┴
txt └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴ └────┘ └┘ ┴
par └───────┘ └─┘ ┴ ┴ └───────┘ └─┘ ┴ ┴ └────┘ └┘ ┴
pid ┴ └─┘ ┴ ┴ ┴ └─┘ ┴ ┴ ┴┴ └┘ ┴
st ────────────────────────────────────────────────────────┘└─
630 by_cases xy : x = y, { simp [xy] },
id ┴ ┴ ┴ └┘
src └───────┘ └─┘ ┴┴┴ └────┘ └┘
typ └───────┘ └─┘┴┴┴┴┴ └────┘└┘└┘
doc └───────┘ └─┘ ┴ ┴ └────┘ └┘
txt └───────┘ └─┘ ┴ ┴ └────┘ └┘
par └───────┘ └─┘ ┴ ┴ └────┘ └┘
pid ┴ └─┘ ┴ ┴ ┴┴ ┴┴
st ────────────────────┘└──┘└────────┘└┘└
631 simp [not_mem_cons_of_ne_of_not_mem xy xl,
id └───────────────────────────┘ └┘ └┘
src └────┘└───────────────────────────┘┴ ┴ └─
typ └────┘└───────────────────────────┘┴└┘┴└┘└─
doc └────┘ ┴ ┴ └─
txt └────┘ ┴ ┴ └─
par └────┘ ┴ ┴ └─
pid ┴┴ ┴ ┴ └─
st ─────────────────────────────────────────────
632 not_mem_cons_of_ne_of_not_mem (ne.symm xy) yl],
id └───────────────────────────┘ └─────┘ └┘ └┘
src ───────┘└───────────────────────────┘┴ └─────┘┴ └┘ ┴
typ ───────┘└───────────────────────────┘┴ └─────┘┴└┘└┘└┘┴
doc ───────┘ ┴ ┴ └┘ ┴
txt ───────┘ ┴ ┴ └┘ ┴
par ───────┘ ┴ ┴ └┘ ┴
pid ───────┘ ┴ ┴ └┘ ┴
st ─────────────────────────────────────────────────────┘└─
633 constructor
src └──────────┘
typ └──────────┘
doc └──────────┘
txt └──────────┘
par └──────────┘
pid ┴
st ─────────────┘
634 end
st └─┘
635
636 theorem perm_union_left {l₁ l₂ : list α} (t₁ : list α) (h : l₁ ~ l₂) : l₁ ∪ t₁ ~ l₂ ∪ t₁ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
src └──┘ └──┘ ┴ ┴ ┴ ┴
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
doc ┴ ┴
637 begin
st └─────
638 induction h with a _ _ _ ih _ _ _ _ _ _ _ _ ih_1 ih_2; try {simp},
id ┴
src └────────┘ └────────────────────────────────────────┘ └───┘└──┘┴
typ └────────┘┴└────────────────────────────────────────┘ └───┘└──┘┴
doc └────────┘ └────────────────────────────────────────┘ └───┘└──┘┴
txt └────────┘ └────────────────────────────────────────┘ └───┘└──┘┴
par └────────┘ └────────────────────────────────────────┘ └───┘└──┘┴
pid ┴ ┴└───────────────────────────────────────┘ └─────┘
st ─────────────────────────────────────────────────────────────┘└──┘└┘└
639 { exact perm_insert a ih },
id └─────────┘ ┴ └┘
src └────┘└─────────┘┴ ┴ ┴
typ └────┘└─────────┘┴┴┴└┘┴
doc └────┘ ┴ ┴ ┴
txt └────┘ ┴ ┴ ┴
par └────┘ ┴ ┴ ┴
pid ┴ ┴ ┴ ┴
st ───┘└─────────────────────┘└┘└
640 { apply perm_insert_swap },
id └──────────────┘
src └────┘└──────────────┘┴
typ └────┘└──────────────┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴ ┴
st ───┘└─────────────────────┘└┘└
641 { exact ih_1.trans ih_2 }
id └────────┘ └──┘
src └────┘└────────┘┴ ┴
typ └────┘└────────┘┴└──┘┴
doc └────┘ ┴ ┴
txt └────┘ ┴ ┴
par └────┘ ┴ ┴
pid ┴ ┴ ┴
st ─────────────────────────┘└─
642 end
st ──┘
643
644 theorem perm_union_right (l : list α) {t₁ t₂ : list α} (h : t₁ ~ t₂) : l ∪ t₁ ~ l ∪ t₂ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
src └──┘ └──┘ ┴ ┴ ┴ ┴
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
doc ┴ ┴
645 by induction l; simp [*, perm_insert]
id ┴ └─────────┘
src └────────┘ └───────┘└─────────┘└─
typ └────────┘┴ └───────┘└─────────┘└─
doc └────────┘ └───────┘ └─
txt └────────┘ └───────┘ └─
par └────────┘ └───────┘ └─
pid ┴ ┴└──┘ ┴└
st └───────────────────────────────────
646
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
647 -- @[congr]
src ───────────┘
typ ───────────┘
doc ───────────┘
txt ───────────┘
par ───────────┘
pid ───────────┘
st ───────────┘
648 theorem perm_union {l₁ l₂ t₁ t₂ : list α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ∪ t₁ ~ l₂ ∪ t₂ :=
id └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
src └──┘ ┴ ┴ ┴ ┴ ┴
typ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
doc ┴ ┴ ┴
649 trans (perm_union_left t₁ p₁) (perm_union_right l₂ p₂)
id └───┘ └─────────────┘ └┘ └┘ └──────────────┘ └┘ └┘
src └───┘ └─────────────┘ └──────────────┘
typ └───┘ └─────────────┘ └┘ └┘ └──────────────┘ └┘ └┘
650
651 theorem perm_inter_left {l₁ l₂ : list α} (t₁ : list α) : l₁ ~ l₂ → l₁ ∩ t₁ ~ l₂ ∩ t₁ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
src └──┘ └──┘ ┴ ┴ ┴ ┴
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
doc ┴ ┴
652 perm_filter _
id └─────────┘
src └─────────┘
typ └─────────┘
653
654 theorem perm_inter_right (l : list α) {t₁ t₂ : list α} (p : t₁ ~ t₂) : l ∩ t₁ = l ∩ t₂ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
src └──┘ └──┘ ┴ ┴ ┴ ┴
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ └┘
doc ┴
655 by dsimp [(∩), list.inter]; congr; funext a; rw [mem_of_perm p]
id └────────┘ └─────────┘ ┴
src └─────┘ └──┘└────────┘┴ └───┘ └──────┘ └──┘└─────────┘┴ └─
typ └─────┘ └──┘└────────┘┴ └───┘ └──────┘ └──┘└─────────┘┴┴└─
doc └─────┘ └──┘ ┴ └──────┘ └──┘ ┴ └─
txt └─────┘ └──┘ ┴ └───┘ └──────┘ └──┘ ┴ └─
par └─────┘ └──┘ ┴ └───┘ └──────┘ └──┘ ┴ └─
pid ┴┴ └──┘ ┴ └┘ └┘ ┴ ┴└
st └─────────────────────────────────────────────┘└───────────┘┴└
656
src ─
typ ─
doc ─
txt ─
par ─
pid ─
st ─
657 -- @[congr]
src ───────────┘
typ ───────────┘
doc ───────────┘
txt ───────────┘
par ───────────┘
pid ───────────┘
st ───────────┘
658 theorem perm_inter {l₁ l₂ t₁ t₂ : list α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ∩ t₁ ~ l₂ ∩ t₂ :=
id └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
src └──┘ ┴ ┴ ┴ ┴ ┴
typ └──┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴ └┘
doc ┴ ┴ ┴
659 perm_inter_right l₂ p₂ ▸ perm_inter_left t₁ p₁
id └──────────────┘ └┘ └┘ ┴ └─────────────┘ └┘ └┘
src └──────────────┘ ┴ └─────────────┘
typ └──────────────┘ └┘ └┘ ┴ └─────────────┘ └┘ └┘
660 end
661
662 theorem perm_pairwise {R : α → α → Prop} (S : symmetric R) :
id ┴ ┴ └───────┘ ┴
src └───────┘
typ ┴ ┴ └───────┘ ┴
663 ∀ {l₁ l₂ : list α} (p : l₁ ~ l₂), pairwise R l₁ ↔ pairwise R l₂ :=
id └──┘ ┴ └┘ ┴ └┘ └──────┘ ┴ └┘ ┴ └──────┘ ┴ └┘
src └──┘ ┴ └──────┘ ┴ └──────┘
typ └──┘ ┴ └┘ ┴ └┘ └──────┘ ┴ └┘ ┴ └──────┘ ┴ └┘
doc ┴ └──────┘ └──────┘
664 suffices ∀ {l₁ l₂}, l₁ ~ l₂ → pairwise R l₁ → pairwise R l₂, from λ l₁ l₂ p, ⟨this p, this p.symm⟩,
id └┘ └┘ └┘ ┴ └┘ └──────┘ ┴ └┘ └──────┘ ┴ └┘ └┘ └┘ ┴ └──┘ ┴ └──┘ ┴└───┘
src ┴ └──────┘ └──────┘ └───┘
typ └┘ └┘ └┘ ┴ └┘ └──────┘ ┴ └┘ └──────┘ ┴ └┘ └┘ └┘ ┴ └──┘ ┴ └──┘ ┴└───┘
doc ┴ └──────┘ └──────┘
665 λ l₁ l₂ p d, begin
id └┘ └┘ ┴ ┴
typ └┘ └┘ ┴ ┴
st └─────
666 induction d with a l₁ h d IH generalizing l₂,
id ┴
src └────────┘ └───────────────────────────────┘
typ └────────┘┴└───────────────────────────────┘
doc └────────┘ └───────────────────────────────┘
txt └────────┘ └───────────────────────────────┘
par └────────┘ └───────────────────────────────┘
pid ┴ ┴└──────────────┘└──────────────┘
st ─────────────────────────────────────────────┘└─
667 { rw eq_nil_of_perm_nil p, constructor },
id └────────────────┘ ┴
src └─┘└────────────────┘┴ └──────────┘
typ └─┘└────────────────┘┴┴ └──────────┘
doc └─┘ ┴ └──────────┘
txt └─┘ ┴ └──────────┘
par └─┘ ┴ └──────────┘
pid ┴ ┴ ┴
st ───┘└─────────────────────┘└────────────┘└┘└
668 { have : a ∈ l₂ := perm_subset p (mem_cons_self _ _),
id ┴ ┴ └┘ └─────────┘ ┴ └───────────┘
src └─────┘ ┴┴┴ └──┘└─────────┘┴ ┴ └───────────┘└───┘
typ └─────┘┴┴┴┴└┘└──┘└─────────┘┴┴┴ └───────────┘└───┘
doc └─────┘ ┴ ┴ └──┘ ┴ ┴ └───┘
txt └─────┘ ┴ ┴ └──┘ ┴ ┴ └───┘
par └─────┘ ┴ ┴ └──┘ ┴ ┴ └───┘
pid └───┘└┘ ┴ ┴ └──┘ ┴ ┴ └───┘
st ─────────────────────────────────────────────────────┘└─
669 rcases mem_split this with ⟨s₂, t₂, rfl⟩,
id └───────┘ └──┘
src └─────┘└───────┘┴ └─────────────────┘
typ └─────┘└───────┘┴└──┘└─────────────────┘
doc └─────┘ ┴ └─────────────────┘
txt └─────┘ ┴ └─────────────────┘
par └─────┘ ┴ └─────────────────┘
pid ┴ ┴ └─────────────────┘
st ───────────────────────────────────────────┘└─
670 have p' := perm_cons_inv (p.trans perm_middle),
id └───────────┘ └─────┘ └─────────┘
src └─────────┘└───────────┘┴ └─────┘┴└─────────┘┴
typ └─────────┘└───────────┘┴ └─────┘┴└─────────┘┴
doc └─────────┘ ┴ ┴ ┴
txt └─────────┘ ┴ ┴ ┴
par └─────────┘ ┴ ┴ ┴
pid └─────┘┴└─┘ ┴ ┴ ┴
st ─────────────────────────────────────────────────┘└─
671 refine (pairwise_middle S).2 (pairwise_cons.2 ⟨λ b m, _, IH _ p'⟩),
id └─────────────┘ ┴ └───────────┘ └┘ └┘
src └─────┘ └─────────────┘┴ └──┘ └───────────┘└─┘ └───────┘ └─┘ └┘
typ └─────┘ └─────────────┘┴┴└──┘ └───────────┘└─┘ └───────┘└┘└─┘└┘└┘
doc └─────┘ ┴ └──┘ └─┘ └───────┘ └─┘ └┘
txt └─────┘ ┴ └──┘ └─┘ └───────┘ └─┘ └┘
par └─────┘ ┴ └──┘ └─┘ └───────┘ └─┘ └┘
pid ┴ ┴ └──┘ └─┘ └───────┘ └─┘ └┘
st ─────────────────────────────────────────────────────────────────────┘└─
672 exact h _ (perm_subset p'.symm m) }
id ┴ └─────────┘ └─────┘ ┴
src └────┘ └─┘ └─────────┘┴└─────┘┴ └┘
typ └────┘┴└─┘ └─────────┘┴└─────┘┴┴└┘
doc └────┘ └─┘ ┴ ┴ └┘
txt └────┘ └─┘ ┴ ┴ └┘
par └────┘ └─┘ ┴ ┴ └┘
pid ┴ └─┘ ┴ ┴ ┴┴
st ─────────────────────────────────────┘└─
673 end
st ──┘
674
675 theorem perm_nodup {l₁ l₂ : list α} : l₁ ~ l₂ → (nodup l₁ ↔ nodup l₂) :=
id └──┘ ┴ └┘ ┴ └┘ └───┘ └┘ ┴ └───┘ └┘
src └──┘ ┴ └───┘ ┴ └───┘
typ └──┘ ┴ └┘ ┴ └┘ └───┘ └┘ ┴ └───┘ └┘
doc ┴ └───┘ └───┘
676 perm_pairwise $ @ne.symm α
id └───────────┘ └─────┘ ┴
src └───────────┘ └─────┘
typ └───────────┘ └─────┘ ┴
677
678 theorem perm_bind_left {l₁ l₂ : list α} (f : α → list β) (p : l₁ ~ l₂) :
id └──┘ ┴ ┴ └──┘ ┴ └┘ ┴ └┘
src └──┘ └──┘ ┴
typ └──┘ ┴ ┴ └──┘ ┴ └┘ ┴ └┘
doc ┴
679 l₁.bind f ~ l₂.bind f :=
id └┘└───┘ ┴ ┴ └┘└───┘ ┴
src └───┘ ┴ └───┘
typ └┘└───┘ ┴ ┴ └┘└───┘ ┴
doc ┴
680 begin
st └─────
681 induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {simp},
id ┴
src └────────┘ └─────────────────────────────────────────────┘ └──┘
typ └────────┘┴└─────────────────────────────────────────────┘ └──┘
doc └────────┘ └─────────────────────────────────────────────┘ └──┘
txt └────────┘ └─────────────────────────────────────────────┘ └──┘
par └────────┘ └─────────────────────────────────────────────┘ └──┘
pid ┴ ┴└────────────────────────────────────────────┘
st ───────────────────────────────────────────────────────────┘└─────┘└┘└
682 { simp, exact perm_app_right _ IH },
id └────────────┘ └┘
src └──┘ └────┘└────────────┘└─┘ ┴
typ └──┘ └────┘└────────────┘└─┘└┘┴
doc └──┘ └────┘ └─┘ ┴
txt └──┘ └────┘ └─┘ ┴
par └──┘ └────┘ └─┘ ┴
pid ┴ └─┘ ┴
st ───┘└──┘└──────────────────────────┘└┘└
683 { simp, rw [← append_assoc, ← append_assoc], exact perm_app_left _ perm_app_comm },
id └──────────┘ └──────────┘ └───────────┘ └───────────┘
src └──┘ └────┘└──────────┘└──┘└──────────┘┴ └────┘└───────────┘└─┘└───────────┘┴
typ └──┘ └────┘└──────────┘└──┘└──────────┘┴ └────┘└───────────┘└─┘└───────────┘┴
doc └──┘ └────┘ └──┘ ┴ └────┘ └─┘ ┴
txt └──┘ └────┘ └──┘ ┴ └────┘ └─┘ ┴
par └──┘ └────┘ └──┘ ┴ └────┘ └─┘ ┴
pid └──┘ └──┘ ┴ ┴ └─┘ ┴
st ───┘└──┘└──────────────────┘└──────────────┘┴└────────────────────────────────────┘└┘└
684 { exact trans IH₁ IH₂ }
id └───┘ └─┘ └─┘
src └────┘└───┘┴ ┴ ┴
typ └────┘└───┘┴└─┘┴└─┘┴
doc └────┘ ┴ ┴ ┴
txt └────┘ ┴ ┴ ┴
par └────┘ ┴ ┴ ┴
pid ┴ ┴ ┴ ┴
st ───────────────────────┘└─
685 end
st ──┘
686
687 theorem perm_bind_right (l : list α) {f g : α → list β} (h : ∀ a, f a ~ g a) :
id └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
src └──┘ └──┘ ┴
typ └──┘ ┴ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴
doc ┴
688 l.bind f ~ l.bind g :=
id ┴└───┘ ┴ ┴ ┴└───┘ ┴
src └───┘ ┴ └───┘
typ ┴└───┘ ┴ ┴ ┴└───┘ ┴
doc ┴
689 by induction l with a l IH; simp; exact perm_app (h a) IH
id ┴ └──────┘ ┴ ┴ └┘
src └────────┘ └──────────┘ └──┘ └────┘└──────┘┴ ┴ └┘ └
typ └────────┘┴└──────────┘ └──┘ └────┘└──────┘┴ ┴┴┴└┘└┘└
doc └────────┘ └──────────┘ └──┘ └────┘ ┴ ┴ └┘ └
txt └────────┘ └──────────┘ └──┘ └────┘ ┴ ┴ └┘ └
par └────────┘ └──────────┘ └──┘ └────┘ ┴ ┴ └┘ └
pid ┴ ┴└─────────┘ ┴ ┴ ┴ └┘ └
st └───────────────────────────────────────────────────────
690
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
691 theorem perm_product_left {l₁ l₂ : list α} (t₁ : list β) (p : l₁ ~ l₂) : product l₁ t₁ ~ product l₂ t₁ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └─────┘ └┘ └┘ ┴ └─────┘ └┘ └┘
src └──┘ └──┘ ┴ └─────┘ ┴ └─────┘
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └─────┘ └┘ └┘ ┴ └─────┘ └┘ └┘
doc ┴ └─────┘ ┴ └─────┘
692 perm_bind_left _ p
id └────────────┘ ┴
src └────────────┘
typ └────────────┘ ┴
693
694 theorem perm_product_right (l : list α) {t₁ t₂ : list β} (p : t₁ ~ t₂) : product l t₁ ~ product l t₂ :=
id └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └─────┘ ┴ └┘ ┴ └─────┘ ┴ └┘
src └──┘ └──┘ ┴ └─────┘ ┴ └─────┘
typ └──┘ ┴ └──┘ ┴ └┘ ┴ └┘ └─────┘ ┴ └┘ ┴ └─────┘ ┴ └┘
doc ┴ └─────┘ ┴ └─────┘
695 perm_bind_right _ $ λ a, perm_map _ p
id └─────────────┘ ┴ └──────┘ ┴
src └─────────────┘ └──────┘
typ └─────────────┘ ┴ └──────┘ ┴
696
697 @[congr] theorem perm_product {l₁ l₂ : list α} {t₁ t₂ : list β}
id └──┘ ┴ └──┘ ┴
src └───┘ └──┘ └──┘
typ └──┘ ┴ └──┘ ┴
doc └───┘
698 (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : product l₁ t₁ ~ product l₂ t₂ :=
id └┘ ┴ └┘ └┘ ┴ └┘ └─────┘ └┘ └┘ ┴ └─────┘ └┘ └┘
src ┴ ┴ └─────┘ ┴ └─────┘
typ └┘ ┴ └┘ └┘ ┴ └┘ └─────┘ └┘ └┘ ┴ └─────┘ └┘ └┘
doc ┴ ┴ └─────┘ ┴ └─────┘
699 trans (perm_product_left t₁ p₁) (perm_product_right l₂ p₂)
id └───┘ └───────────────┘ └┘ └┘ └────────────────┘ └┘ └┘
src └───┘ └───────────────┘ └────────────────┘
typ └───┘ └───────────────┘ └┘ └┘ └────────────────┘ └┘ └┘
700
701 theorem sublists_cons_perm_append (a : α) (l : list α) :
id ┴ └──┘ ┴
src └──┘
typ ┴ └──┘ ┴
702 sublists (a :: l) ~ sublists l ++ map (cons a) (sublists l) :=
id └──────┘ ┴ └┘ ┴ ┴ └──────┘ ┴ └┘ └─┘ └──┘ ┴ └──────┘ ┴
src └──────┘ └┘ ┴ └──────┘ └┘ └─┘ └──┘ └──────┘
typ └──────┘ ┴ └┘ ┴ ┴ └──────┘ ┴ └┘ └─┘ └──┘ ┴ └──────┘ ┴
doc └──────┘ ┴ └──────┘ └──────┘
703 begin
st └─────
704 simp [sublists, sublists_aux_cons_cons],
id └──────┘ └────────────────────┘
src └────┘└──────┘└┘└────────────────────┘┴
typ └────┘└──────┘└┘└────────────────────┘┴
doc └────┘└──────┘└┘ ┴
txt └────┘ └┘ ┴
par └────┘ └┘ ┴
pid ┴┴ └┘ ┴
st ────────────────────────────────────────┘└─
705 refine skip _ ((skip _ _).trans perm_middle.symm),
id └──┘ └──────────────┘
src └─────┘ └─┘ └──┘└──────────┘└──────────────┘┴
typ └─────┘ └─┘ └──┘└──────────┘└──────────────┘┴
doc └─────┘ └─┘ └──────────┘ ┴
txt └─────┘ └─┘ └──────────┘ ┴
par └─────┘ └─┘ └──────────┘ ┴
pid ┴ └─┘ └──────────┘ ┴
st ──────────────────────────────────────────────────┘└─
706 induction sublists_aux l cons with b l IH; simp,
id └──────────┘ ┴ └──┘
src └────────┘└──────────┘┴ ┴└──┘└──────────┘ └──┘
typ └────────┘└──────────┘┴┴┴└──┘└──────────┘ └──┘
doc └────────┘ ┴ ┴ └──────────┘ └──┘
txt └────────┘ ┴ ┴ └──────────┘ └──┘
par └────────┘ ┴ ┴ └──────────┘ └──┘
pid ┴ ┴ ┴ ┴└─────────┘
st ────────────────────────────────────────────────┘└─
707 exact skip b ((skip _ IH).trans perm_middle.symm)
id ┴ └──┘ └┘ └──────────────┘
src └────┘ ┴ ┴ └──┘└─┘ └──────┘└──────────────┘└┘
typ └────┘ ┴┴┴ └──┘└─┘└┘└──────┘└──────────────┘└┘
doc └────┘ ┴ ┴ └─┘ └──────┘ └┘
txt └────┘ ┴ ┴ └─┘ └──────┘ └┘
par └────┘ ┴ ┴ └─┘ └──────┘ └┘
pid ┴ ┴ ┴ └─┘ └──────┘ ┴┴
st ───────────────────────────────────────────────────┘
708 end
st └─┘
709
710 theorem sublists_perm_sublists' : ∀ l : list α, sublists l ~ sublists' l
id ┴ └──┘ ┴ └──────┘ ┴ ┴ └───────┘ ┴
src └──┘ └──────┘ ┴ └───────┘
typ ┴ └──┘ ┴ └──────┘ ┴ ┴ └───────┘ ┴
doc └──────┘ ┴ └───────┘
711 | [] := perm.refl _
id └┘ └───────┘
src └┘ └───────┘
typ └┘ └───────┘
712 | (a::l) := let IH := sublists_perm_sublists' l in
id └┘┴ └┘ └─────────────────────┘
src └┘
typ └┘┴ └┘ └─────────────────────┘
713 by rw sublists'_cons; exact
id └────────────┘
src └─┘└────────────┘ └─────
typ └─┘└────────────┘ └─────
doc └─┘ └─────
txt └─┘ └─────
par └─┘ └─────
pid ┴ └
st └─────────────────────────
714 (sublists_cons_perm_append _ _).trans (perm_app IH (perm_map _ IH))
id └───────────────────────┘ └──────┘ └──────┘ └┘
src ─┘ └───────────────────────┘└──────────┘ └──────┘┴ ┴ └──────┘└─┘ └──
typ ─┘ └───────────────────────┘└──────────┘ └──────┘┴ ┴ └──────┘└─┘└┘└──
doc ─┘ └──────────┘ ┴ ┴ └─┘ └──
txt ─┘ └──────────┘ ┴ ┴ └─┘ └──
par ─┘ └──────────┘ ┴ ┴ └─┘ └──
pid ─┘ └──────────┘ ┴ ┴ └─┘ └┘└
st ──────────────────────────────────────────────────────────────────────
715
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
716 theorem revzip_sublists (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
717 ∀ l₁ l₂, (l₁, l₂) ∈ revzip l.sublists → l₁ ++ l₂ ~ l :=
id └┘ └┘ ┴└┘ └┘ ┴ └────┘ ┴└───────┘ └┘ └┘ └┘ ┴ ┴
src ┴ ┴ └────┘ └───────┘ └┘ ┴
typ └┘ └┘ ┴└┘ └┘ ┴ └────┘ ┴└───────┘ └┘ └┘ └┘ ┴ ┴
doc └───────┘ ┴
718 begin
st └─────
719 rw revzip,
id └────┘
src └─┘└────┘
typ └─┘└────┘
doc └─┘
txt └─┘
par └─┘
pid ┴
st ──────────┘└─
720 apply list.reverse_rec_on l,
id └─────────────────┘ ┴
src └────┘└─────────────────┘┴
typ └────┘└─────────────────┘┴┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴ ┴
st ────────────────────────────┘└─
721 { intros l₁ l₂ h, simp at h, simp [h] },
id ┴
src └────────────┘ └───────┘ └────┘ └┘
typ └────────────┘ └───────┘ └────┘┴└┘
doc └────────────┘ └───────┘ └────┘ └┘
txt └────────────┘ └───────┘ └────┘ └┘
par └────────────┘ └───────┘ └────┘ └┘
pid └──────┘ ┴└──┘ ┴┴ ┴┴
st ───┘└────────────┘└─────────┘└─────────┘└┘└
722 { intros l a IH l₁ l₂ h,
src └───────────────────┘
typ └───────────────────┘
doc └───────────────────┘
txt └───────────────────┘
par └───────────────────┘
pid └─────────────┘
st ────────────────────────┘└─
723 rw [sublists_concat, reverse_append, zip_append, ← map_reverse,
id └─────────────┘ └────────────┘ └────────┘ └─────────┘
src └──┘└─────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
typ └──┘└─────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
doc └──┘ └┘ └┘ └──┘ └─
txt └──┘ └┘ └┘ └──┘ └─
par └──┘ └┘ └┘ └──┘ └─
pid └┘ └┘ └┘ └──┘ └─
st ──────────────────────┘└──────────────┘└──────────┘└─────────────┘└─
724 zip_map_right, zip_map_left] at h; [simp at h, simp],
id └───────────┘ └──────────┘ ┴
src ───────┘└───────────┘└┘└──────────┘└────┘ ┴└───────┘ └──┘
typ ───────┘└───────────┘└┘└──────────┘└────┘ ┴└───────┘ └──┘
doc ───────┘ └┘ └────┘ └───────┘ └──┘
txt ───────┘ └┘ └────┘ └───────┘ └──┘
par ───────┘ └┘ └────┘ └───────┘ └──┘
pid ───────┘ └┘ ┴└───┘ ┴└──┘
st ────────────────────┘└────────────┘┴└──────────────────────┘└─
725 rcases h with ⟨l₁, l₂', h, rfl, rfl⟩ | ⟨l₁', l₂, h, rfl, rfl⟩,
id ┴
src └─────┘ └───────────────────────────────────────────────────┘
typ └─────┘┴└───────────────────────────────────────────────────┘
doc └─────┘ └───────────────────────────────────────────────────┘
txt └─────┘ └───────────────────────────────────────────────────┘
par └─────┘ └───────────────────────────────────────────────────┘
pid ┴ └───────────────────────────────────────────────────┘
st ────────────────────────────────────────────────────────────────┘└─
726 { rw ← append_assoc,
id └──────────┘
src └───┘└──────────┘
typ └───┘└──────────┘
doc └───┘
txt └───┘
par └───┘
pid └─┘
st ─────┘└───────────────┘└─
727 exact perm_app_left _ (IH _ _ h) },
id └───────────┘ └┘ ┴
src └────┘└───────────┘└─┘ └───┘ └┘
typ └────┘└───────────┘└─┘ └┘└───┘┴└┘
doc └────┘ └─┘ └───┘ └┘
txt └────┘ └─┘ └───┘ └┘
par └────┘ └─┘ └───┘ └┘
pid ┴ └─┘ └───┘ ┴┴
st ──────────────────────────────────────┘└┘└
728 { rw append_assoc,
id └──────────┘
src └─┘└──────────┘
typ └─┘└──────────┘
doc └─┘
txt └─┘
par └─┘
pid ┴
st ────────────────────┘└─
729 apply (perm_app_right _ perm_app_comm).trans,
id └────────────┘ └───────────┘
src └────┘ └────────────┘└─┘└───────────┘└─────┘
typ └────┘ └────────────┘└─┘└───────────┘└─────┘
doc └────┘ └─┘ └─────┘
txt └────┘ └─┘ └─────┘
par └────┘ └─┘ └─────┘
pid ┴ └─┘ └────┘┴
st ─────────────────────────────────────────────────┘└─
730 rw ← append_assoc,
id └──────────┘
src └───┘└──────────┘
typ └───┘└──────────┘
doc └───┘
txt └───┘
par └───┘
pid └─┘
st ──────────────────────┘└─
731 exact perm_app_left _ (IH _ _ h) } }
id └───────────┘ └┘ ┴
src └────┘└───────────┘└─┘ └───┘ └┘
typ └────┘└───────────┘└─┘ └┘└───┘┴└┘
doc └────┘ └─┘ └───┘ └┘
txt └────┘ └─┘ └───┘ └┘
par └────┘ └─┘ └───┘ └┘
pid ┴ └─┘ └───┘ ┴┴
st ──────────────────────────────────────┘└───
732 end
st ──┘
733
734 theorem revzip_sublists' (l : list α) :
id └──┘ ┴
src └──┘
typ └──┘ ┴
735 ∀ l₁ l₂, (l₁, l₂) ∈ revzip l.sublists' → l₁ ++ l₂ ~ l :=
id └┘ └┘ ┴└┘ └┘ ┴ └────┘ ┴└────────┘ └┘ └┘ └┘ ┴ ┴
src ┴ ┴ └────┘ └────────┘ └┘ ┴
typ └┘ └┘ ┴└┘ └┘ ┴ └────┘ ┴└────────┘ └┘ └┘ └┘ ┴ ┴
doc └────────┘ ┴
736 begin
st └─────
737 rw revzip,
id └────┘
src └─┘└────┘
typ └─┘└────┘
doc └─┘
txt └─┘
par └─┘
pid ┴
st ──────────┘└─
738 induction l with a l IH; intros l₁ l₂ h,
id ┴
src └────────┘ └──────────┘ └────────────┘
typ └────────┘┴└──────────┘ └────────────┘
doc └────────┘ └──────────┘ └────────────┘
txt └────────┘ └──────────┘ └────────────┘
par └────────┘ └──────────┘ └────────────┘
pid ┴ ┴└─────────┘ └──────┘
st ────────────────────────────────────────┘└─
739 { simp at h, simp [h] },
id ┴
src └───────┘ └────┘ └┘
typ └───────┘ └────┘┴└┘
doc └───────┘ └────┘ └┘
txt └───────┘ └────┘ └┘
par └───────┘ └────┘ └┘
pid ┴└──┘ ┴┴ ┴┴
st ───┘└───────┘└─────────┘└┘└
740 { rw [sublists'_cons, reverse_append, zip_append, ← map_reverse,
id └────────────┘ └────────────┘ └────────┘ └─────────┘
src └──┘└────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
typ └──┘└────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
doc └──┘ └┘ └┘ └──┘ └─
txt └──┘ └┘ └┘ └──┘ └─
par └──┘ └┘ └┘ └──┘ └─
pid └┘ └┘ └┘ └──┘ └─
st ─────────────────────┘└──────────────┘└──────────┘└─────────────┘└─
741 zip_map_right, zip_map_left] at h; [simp at h, simp],
id └───────────┘ └──────────┘ ┴
src ───────┘└───────────┘└┘└──────────┘└────┘ ┴└───────┘ └──┘
typ ───────┘└───────────┘└┘└──────────┘└────┘ ┴└───────┘ └──┘
doc ───────┘ └┘ └────┘ └───────┘ └──┘
txt ───────┘ └┘ └────┘ └───────┘ └──┘
par ───────┘ └┘ └────┘ └───────┘ └──┘
pid ───────┘ └┘ ┴└───┘ ┴└──┘
st ────────────────────┘└────────────┘┴└──────────────────────┘└─
742 rcases h with ⟨l₁, l₂', h, rfl, rfl⟩ | ⟨l₁', l₂, h, rfl, rfl⟩,
id ┴
src └─────┘ └───────────────────────────────────────────────────┘
typ └─────┘┴└───────────────────────────────────────────────────┘
doc └─────┘ └───────────────────────────────────────────────────┘
txt └─────┘ └───────────────────────────────────────────────────┘
par └─────┘ └───────────────────────────────────────────────────┘
pid ┴ └───────────────────────────────────────────────────┘
st ────────────────────────────────────────────────────────────────┘└─
743 { exact perm_middle.trans (skip _ (IH _ _ h)) },
id └───────────────┘ └──┘ └┘ ┴
src └────┘└───────────────┘┴ └──┘└─┘ └───┘ └─┘
typ └────┘└───────────────┘┴ └──┘└─┘ └┘└───┘┴└─┘
doc └────┘ ┴ └─┘ └───┘ └─┘
txt └────┘ ┴ └─┘ └───┘ └─┘
par └────┘ ┴ └─┘ └───┘ └─┘
pid ┴ ┴ └─┘ └───┘ └┘┴
st ─────┘└──────────────────────────────────────────┘└┘└
744 { exact skip _ (IH _ _ h) } }
id └──┘ └┘ ┴
src └────┘└──┘└─┘ └───┘ └┘
typ └────┘└──┘└─┘ └┘└───┘┴└┘
doc └────┘ └─┘ └───┘ └┘
txt └────┘ └─┘ └───┘ └┘
par └────┘ └─┘ └───┘ └┘
pid ┴ └─┘ └───┘ ┴┴
st ─────────────────────────────┘└───
745 end
st ──┘
746
747 theorem perm_lookmap (f : α → option α) {l₁ l₂ : list α}
id ┴ └────┘ ┴ └──┘ ┴
src └────┘ └──┘
typ ┴ └────┘ ┴ └──┘ ┴
748 (H : pairwise (λ a b, ∀ (c ∈ f a) (d ∈ f b), a = b ∧ c = d) l₁)
id └──────┘ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
src └──────┘ ┴ ┴ ┴ ┴
typ └──────┘ ┴ ┴ ┴┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘
doc └──────┘
749 (p : l₁ ~ l₂) : lookmap f l₁ ~ lookmap f l₂ :=
id └┘ ┴ └┘ └─────┘ ┴ └┘ ┴ └─────┘ ┴ └┘
src ┴ └─────┘ ┴ └─────┘
typ └┘ ┴ └┘ └─────┘ ┴ └┘ ┴ └─────┘ ┴ └┘
doc ┴ └─────┘ ┴ └─────┘
750 begin
st └─────
751 let F := λ a b, ∀ (c ∈ f a) (d ∈ f b), a = b ∧ c = d,
id ┴ ┴
src └───────┘ └────┘ └────┘ ┴ └─────┘ ┴ ┴ ┴ ┴┴┴ ┴ ┴ ┴ ┴
typ └───────┘ └────┘ └────┘ ┴ └─────┘┴┴ ┴ ┴ ┴┴┴ ┴ ┴ ┴ ┴
doc └───────┘ └────┘ └────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
txt └───────┘ └────┘ └────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
par └───────┘ └────┘ └────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
pid └───┘┴└─┘ └────┘ └────┘ ┴ └─────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴
st ─────────────────────────────────────────────────────┘└─
752 change pairwise F l₁ at H,
id └──────┘ ┴ └┘
src └─────┘└──────┘┴ ┴ └───┘
typ └─────┘└──────┘┴┴┴└┘└───┘
doc └─────┘└──────┘┴ ┴ └───┘
txt └─────┘ ┴ ┴ └───┘
par └─────┘ ┴ ┴ └───┘
pid ┴ ┴ ┴ ┴└──┘
st ──────────────────────────┘└─
753 induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {simp},
id ┴
src └────────┘ └─────────────────────────────────────────────┘ └──┘
typ └────────┘┴└─────────────────────────────────────────────┘ └──┘
doc └────────┘ └─────────────────────────────────────────────┘ └──┘
txt └────────┘ └─────────────────────────────────────────────┘ └──┘
par └────────┘ └─────────────────────────────────────────────┘ └──┘
pid ┴ ┴└────────────────────────────────────────────┘
st ───────────────────────────────────────────────────────────┘└─────┘└┘└
754 { cases h : f a,
id ┴ ┴
src └────┘ └─┘ ┴
typ └────┘ └─┘┴┴┴
doc └────┘ └─┘ ┴
txt └────┘ └─┘ ┴
par └────┘ └─┘ ┴
pid ┴ └─┘ ┴
st ───┘└───────────┘└─
755 { simp [h], exact (IH (pairwise_cons.1 H).2).skip _ },
id ┴ └┘ └───────────┘ ┴
src └────┘ ┴ └────┘ ┴ └───────────┘└─┘ └──────────┘
typ └────┘┴┴ └────┘ └┘┴ └───────────┘└─┘┴└──────────┘
doc └────┘ ┴ └────┘ ┴ └─┘ └──────────┘
txt └────┘ ┴ └────┘ ┴ └─┘ └──────────┘
par └────┘ ┴ └────┘ ┴ └─┘ └──────────┘
pid ┴┴ ┴ ┴ ┴ └─┘ └─────────┘┴
st ─────┘└──────┘└────────────────────────────────────────┘└┘└
756 { simp [lookmap_cons_some _ _ h], exact p.skip _ } },
id └───────────────┘ ┴ └────┘
src └────┘└───────────────┘└───┘ ┴ └────┘└────┘└─┘
typ └────┘└───────────────┘└───┘┴┴ └────┘└────┘└─┘
doc └────┘ └───┘ ┴ └────┘ └─┘
txt └────┘ └───┘ ┴ └────┘ └─┘
par └────┘ └───┘ ┴ └────┘ └─┘
pid ┴┴ └───┘ ┴ ┴ └┘┴
st ───────────────────────────────────┘└───────────────┘└──┘└
757 { cases h₁ : f a with c; cases h₂ : f b with d,
id ┴ ┴ ┴ ┴
src └────┘ └─┘ ┴ └─────┘ └────┘ └─┘ ┴ └─────┘
typ └────┘ └─┘┴┴┴└─────┘ └────┘ └─┘┴┴┴└─────┘
doc └────┘ └─┘ ┴ └─────┘ └────┘ └─┘ ┴ └─────┘
txt └────┘ └─┘ ┴ └─────┘ └────┘ └─┘ ┴ └─────┘
par └────┘ └─┘ ┴ └─────┘ └────┘ └─┘ ┴ └─────┘
pid ┴ └─┘ ┴ └─────┘ ┴ └─┘ ┴ └─────┘
st ───┘└──────────────────────────────────────────┘└─
758 { simp [h₁, h₂], apply swap },
id └┘ └┘ └──┘
src └────┘ └┘ ┴ └────┘└──┘┴
typ └────┘└┘└┘└┘┴ └────┘└──┘┴
doc └────┘ └┘ ┴ └────┘ ┴
txt └────┘ └┘ ┴ └────┘ ┴
par └────┘ └┘ ┴ └────┘ ┴
pid ┴┴ └┘ ┴ ┴ ┴
st ─────┘└───────────┘└───────────┘└┘└
759 { simp [h₁, lookmap_cons_some _ _ h₂], apply swap },
id └┘ └───────────────┘ └┘ └──┘
src └────┘ └┘└───────────────┘└───┘ ┴ └────┘└──┘┴
typ └────┘└┘└┘└───────────────┘└───┘└┘┴ └────┘└──┘┴
doc └────┘ └┘ └───┘ ┴ └────┘ ┴
txt └────┘ └┘ └───┘ ┴ └────┘ ┴
par └────┘ └┘ └───┘ ┴ └────┘ ┴
pid ┴┴ └┘ └───┘ ┴ ┴ ┴
st ─────┘└─────────────────────────────────┘└───────────┘└┘└
760 { simp [lookmap_cons_some _ _ h₁, h₂], apply swap },
id └───────────────┘ └┘ └┘ └──┘
src └────┘└───────────────┘└───┘ └┘ ┴ └────┘└──┘┴
typ └────┘└───────────────┘└───┘└┘└┘└┘┴ └────┘└──┘┴
doc └────┘ └───┘ └┘ ┴ └────┘ ┴
txt └────┘ └───┘ └┘ ┴ └────┘ ┴
par └────┘ └───┘ └┘ ┴ └────┘ ┴
pid ┴┴ └───┘ └┘ ┴ ┴ ┴
st ─────┘└─────────────────────────────────┘└───────────┘└┘└
761 { simp [lookmap_cons_some _ _ h₁, lookmap_cons_some _ _ h₂],
id └───────────────┘ └┘ └───────────────┘ └┘
src └────┘└───────────────┘└───┘ └┘└───────────────┘└───┘ ┴
typ └────┘└───────────────┘└───┘└┘└┘└───────────────┘└───┘└┘┴
doc └────┘ └───┘ └┘ └───┘ ┴
txt └────┘ └───┘ └┘ └───┘ ┴
par └────┘ └───┘ └┘ └───┘ ┴
pid ┴┴ └───┘ └┘ └───┘ ┴
st ──────────────────────────────────────────────────────────────┘└─
762 rcases (pairwise_cons.1 H).1 _ (or.inl rfl) _ h₂ _ h₁ with ⟨rfl, rfl⟩,
id └───────────┘ ┴ └────┘ └─┘ └┘ └┘
src └─────┘ └───────────┘└─┘ └────┘ └────┘┴└─┘└──┘ └─┘ └──────────────┘
typ └─────┘ └───────────┘└─┘┴└────┘ └────┘┴└─┘└──┘└┘└─┘└┘└──────────────┘
doc └─────┘ └─┘ └────┘ ┴ └──┘ └─┘ └──────────────┘
txt └─────┘ └─┘ └────┘ ┴ └──┘ └─┘ └──────────────┘
par └─────┘ └─┘ └────┘ ┴ └──┘ └─┘ └──────────────┘
pid ┴ └─┘ └────┘ ┴ └──┘ └─┘ └──────────────┘
st ──────────────────────────────────────────────────────────────────────────┘└─
763 refl } },
src └───┘
typ └───┘
doc └───┘
txt └───┘
par └───┘
pid ┴
st ──────────┘└──┘└
764 { refine (IH₁ H).trans (IH₂ ((perm_pairwise _ p₁).1 H)),
id └─┘ └─┘ └───────────┘ └┘ ┴
src └─────┘ ┴ └──────┘ ┴ └───────────┘└─┘ └──┘ └┘
typ └─────┘ └─┘┴ └──────┘ └─┘┴ └───────────┘└─┘└┘└──┘┴└┘
doc └─────┘ ┴ └──────┘ ┴ └─┘ └──┘ └┘
txt └─────┘ ┴ └──────┘ ┴ └─┘ └──┘ └┘
par └─────┘ ┴ └──────┘ ┴ └─┘ └──┘ └┘
pid ┴ ┴ └──────┘ ┴ └─┘ └──┘ └┘
st ────────────────────────────────────────────────────────┘└─
765 exact λ a b h c h₁ d h₂, (h d h₂ c h₁).imp eq.symm eq.symm }
id └─────┘
src └────┘ └────────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴└─────┘┴
typ └────┘ └────────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴└─────┘┴
doc └────┘ └────────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
txt └────┘ └────────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
par └────┘ └────────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
pid ┴ └────────────────┘ ┴ ┴ ┴ ┴ └────┘ ┴ ┴
st ──────────────────────────────────────────────────────────────┘└─
766 end
st ──┘
767
768 theorem perm_erasep (f : α → Prop) [decidable_pred f] {l₁ l₂ : list α}
id ┴ └────────────┘ ┴ └──┘ ┴
src └────────────┘ └──┘
typ ┴ └────────────┘ ┴ └──┘ ┴
769 (H : pairwise (λ a b, f a → f b → false) l₁)
id └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ └┘
src └──────┘ └───┘
typ └──────┘ ┴ ┴ ┴ ┴ ┴ ┴ └───┘ └┘
doc └──────┘
770 (p : l₁ ~ l₂) : erasep f l₁ ~ erasep f l₂ :=
id └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
src ┴ └────┘ ┴ └────┘
typ └┘ ┴ └┘ └────┘ ┴ └┘ ┴ └────┘ ┴ └┘
doc ┴ ┴
771 begin
st └─────
772 let F := λ a b, f a → f b → false,
id ┴ └───┘
src └───────┘ └────┘ ┴ ┴ ┴ ┴ ┴ ┴└───┘
typ └───────┘ └────┘ ┴ ┴ ┴┴┴ ┴ ┴└───┘
doc └───────┘ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
txt └───────┘ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
par └───────┘ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
pid └───┘┴└─┘ └────┘ ┴ ┴ ┴ ┴ ┴ ┴
st ──────────────────────────────────┘└─
773 change pairwise F l₁ at H,
id └──────┘ ┴ └┘
src └─────┘└──────┘┴ ┴ └───┘
typ └─────┘└──────┘┴┴┴└┘└───┘
doc └─────┘└──────┘┴ ┴ └───┘
txt └─────┘ ┴ ┴ └───┘
par └─────┘ ┴ ┴ └───┘
pid ┴ ┴ ┴ ┴└──┘
st ──────────────────────────┘└─
774 induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {simp},
id ┴
src └────────┘ └─────────────────────────────────────────────┘ └──┘
typ └────────┘┴└─────────────────────────────────────────────┘ └──┘
doc └────────┘ └─────────────────────────────────────────────┘ └──┘
txt └────────┘ └─────────────────────────────────────────────┘ └──┘
par └────────┘ └─────────────────────────────────────────────┘ └──┘
pid ┴ ┴└────────────────────────────────────────────┘
st ───────────────────────────────────────────────────────────┘└─────┘└┘└
775 { by_cases h : f a,
id ┴ ┴
src └───────┘ └─┘ ┴
typ └───────┘ └─┘┴┴┴
doc └───────┘ └─┘ ┴
txt └───────┘ └─┘ ┴
par └───────┘ └─┘ ┴
pid ┴ └─┘ ┴
st ───┘└──────────────┘└─
776 { simp [h, p] },
id ┴ ┴
src └────┘ └┘ └┘
typ └────┘┴└┘┴└┘
doc └────┘ └┘ └┘
txt └────┘ └┘ └┘
par └────┘ └┘ └┘
pid ┴┴ └┘ ┴┴
st ─────┘└──────────┘└┘└
777 { simp [h], exact (IH (pairwise_cons.1 H).2).skip _ } },
id ┴ └┘ └───────────┘ ┴
src └────┘ ┴ └────┘ ┴ └───────────┘└─┘ └──────────┘
typ └────┘┴┴ └────┘ └┘┴ └───────────┘└─┘┴└──────────┘
doc └────┘ ┴ └────┘ ┴ └─┘ └──────────┘
txt └────┘ ┴ └────┘ ┴ └─┘ └──────────┘
par └────┘ ┴ └────┘ ┴ └─┘ └──────────┘
pid ┴┴ ┴ ┴ ┴ └─┘ └─────────┘┴
st ─────────────┘└────────────────────────────────────────┘└──┘└
778 { by_cases h₁ : f a; by_cases h₂ : f b; simp [h₁, h₂],
id ┴ ┴ ┴ ┴ └┘ └┘
src └───────┘ └─┘ ┴ └───────┘ └─┘ ┴ └────┘ └┘ ┴
typ └───────┘ └─┘┴┴┴ └───────┘ └─┘┴┴┴ └────┘└┘└┘└┘┴
doc └───────┘ └─┘ ┴ └───────┘ └─┘ ┴ └────┘ └┘ ┴
txt └───────┘ └─┘ ┴ └───────┘ └─┘ ┴ └────┘ └┘ ┴
par └───────┘ └─┘ ┴ └───────┘ └─┘ ┴ └────┘ └┘ ┴
pid ┴ └─┘ ┴ ┴ └─┘ ┴ ┴┴ └┘ ┴
st ───┘└─────────────────────────────────────────────────┘└─
779 { cases (pairwise_cons.1 H).1 _ (or.inl rfl) h₂ h₁ },
id └───────────┘ ┴ └────┘ └─┘ └┘ └┘
src └────┘ └───────────┘└─┘ └────┘ └────┘┴└─┘└┘ ┴ ┴
typ └────┘ └───────────┘└─┘┴└────┘ └────┘┴└─┘└┘└┘┴└┘┴
doc └────┘ └─┘ └────┘ ┴ └┘ ┴ ┴
txt └────┘ └─┘ └────┘ ┴ └┘ ┴ ┴
par └────┘ └─┘ └────┘ ┴ └┘ ┴ ┴
pid ┴ └─┘ └────┘ ┴ └┘ ┴ ┴
st ─────┘└───────────────────────────────────────────────┘└┘└
780 { apply swap } },
id └──┘
src └────┘└──┘┴
typ └────┘└──┘┴
doc └────┘ ┴
txt └────┘ ┴
par └────┘ ┴
pid ┴ ┴
st ────────────────┘└──┘└
781 { refine (IH₁ H).trans (IH₂ ((perm_pairwise _ p₁).1 H)),
id └─┘ └─┘ └───────────┘ └┘ ┴
src └─────┘ ┴ └──────┘ ┴ └───────────┘└─┘ └──┘ └┘
typ └─────┘ └─┘┴ └──────┘ └─┘┴ └───────────┘└─┘└┘└──┘┴└┘
doc └─────┘ ┴ └──────┘ ┴ └─┘ └──┘ └┘
txt └─────┘ ┴ └──────┘ ┴ └─┘ └──┘ └┘
par └─────┘ ┴ └──────┘ ┴ └─┘ └──┘ └┘
pid ┴ ┴ └──────┘ ┴ └─┘ └──┘ └┘
st ────────────────────────────────────────────────────────┘└─
782 exact λ a b h h₁ h₂, h h₂ h₁ }
src └────┘ └────────────┘ ┴ ┴ ┴
typ └────┘ └────────────┘ ┴ ┴ ┴
doc └────┘ └────────────┘ ┴ ┴ ┴
txt └────┘ └────────────┘ ┴ ┴ ┴
par └────┘ └────────────┘ ┴ ┴ ┴
pid ┴ └────────────┘ ┴ ┴ ┴
st ────────────────────────────────┘└─
783 end
st ──┘
784
785 /- enumerating permutations -/
786
787 section permutations
788
789 theorem permutations_aux2_fst (t : α) (ts : list α) (r : list β) : ∀ (ys : list α) (f : list α → β),
id ┴ └──┘ ┴ └──┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴ ┴
src └──┘ └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴ ┴
790 (permutations_aux2 t ts r ys f).1 = ys ++ ts
id └───────────────┘ ┴ └┘ ┴ └┘ ┴ ┴ ┴ └┘ └┘ └┘
src └───────────────┘ ┴ ┴ └┘
typ └───────────────┘ ┴ └┘ ┴ └┘ ┴ ┴ ┴ └┘ └┘ └┘
791 | [] f := rfl
id └┘ └─┘
src └┘ └─┘
typ └┘ └─┘
792 | (y::ys) f := match _, permutations_aux2_fst ys _ : ∀ o : list α × list β, o.1 = ys ++ ts →
id ┴└┘└┘ ┴ └───────────────────┘ └──┘ ┴ ┴ └──┘ ┴ ┴┴ ┴ └┘ └┘
src └┘ └──┘ ┴ └──┘ ┴ ┴ └┘
typ ┴└┘└┘ ┴ └───────────────────┘ └──┘ ┴ ┴ └──┘ ┴ ┴┴ ┴ └┘ └┘
793 (permutations_aux2._match_1 t y f o).1 = y :: ys ++ ts with
id └────────────────────────┘ ┴ ┴ ┴ ┴ └┘ └┘ └┘
src └────────────────────────┘ ┴ ┴ └┘ └┘
typ └────────────────────────┘ ┴ ┴ ┴ ┴ └┘ └┘ └┘
794 | ⟨_, zs⟩, rfl := rfl
id └─┘ └─┘
src └─┘ └─┘
typ └─┘ └─┘
795 end
796
797 @[simp] theorem permutations_aux2_snd_nil (t : α) (ts : list α) (r : list β) (f : list α → β) :
id ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ ┴
src └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ ┴
doc └──┘
798 (permutations_aux2 t ts r [] f).2 = r := rfl
id └───────────────┘ ┴ └┘ ┴ └┘ ┴ ┴ ┴ ┴ └─┘
src └───────────────┘ └┘ ┴ ┴ └─┘
typ └───────────────┘ ┴ └┘ ┴ └┘ ┴ ┴ ┴ ┴ └─┘
799
800 @[simp] theorem permutations_aux2_snd_cons (t : α) (ts : list α) (r : list β) (y : α) (ys : list α) (f : list α → β) :
id ┴ └──┘ ┴ └──┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴
src └──┘ └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ ┴ ┴ └──┘ ┴ └──┘ ┴ ┴
doc └──┘
801 (permutations_aux2 t ts r (y::ys) f).2 = f (t :: y :: ys ++ ts) ::
id └───────────────┘ ┴ └┘ ┴ ┴└┘└┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ └┘ └┘ └┘ └┘ └┘
src └───────────────┘ └┘ ┴ ┴ └┘ └┘ └┘ └┘
typ └───────────────┘ ┴ └┘ ┴ ┴└┘└┘ ┴ ┴ ┴ ┴ ┴ └┘ ┴ └┘ └┘ └┘ └┘ └┘
802 (permutations_aux2 t ts r ys (λx : list α, f (y::x))).2 :=
id └───────────────┘ ┴ └┘ ┴ └┘ └──┘ ┴ ┴ ┴└┘┴ ┴
src └───────────────┘ └──┘ └┘ ┴
typ └───────────────┘ ┴ └┘ ┴ └┘ └──┘ ┴ ┴ ┴└┘┴ ┴
803 match _, permutations_aux2_fst t ts r _ _ : ∀ o : list α × list β, o.1 = ys ++ ts →
id └───────────────────┘ ┴ └┘ ┴ └──┘ ┴ ┴ └──┘ ┴ ┴┴ ┴ └┘ └┘ └┘
src └───────────────────┘ └──┘ ┴ └──┘ ┴ ┴ └┘
typ └───────────────────┘ ┴ └┘ ┴ └──┘ ┴ ┴ └──┘ ┴ ┴┴ ┴ └┘ └┘ └┘
804 (permutations_aux2._match_1 t y f o).2 = f (t :: y :: ys ++ ts) :: o.2 with
id └────────────────────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ └┘ └┘ └┘ └┘ └┘ ┴┴
src └────────────────────────┘ ┴ ┴ └┘ └┘ └┘ └┘ ┴
typ └────────────────────────┘ ┴ ┴ ┴ ┴ ┴ ┴ ┴ ┴ └┘ ┴ └┘ └┘ └┘ └┘ └┘ ┴┴
805 | ⟨_, zs⟩, rfl := rfl
id └─┘ └─┘
src └─┘ └─┘
typ └─┘ └─┘
806 end
807
808 theorem permutations_aux2_append (t : α) (ts : list α) (r : list β) (ys : list α) (f : list α → β) :
id ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ ┴
src └──┘ └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ ┴
809 (permutations_aux2 t ts nil ys f).2 ++ r = (permutations_aux2 t ts r ys f).2 :=
id └───────────────┘ ┴ └┘ └─┘ └┘ ┴ ┴ └┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ └┘ ┴ ┴
src └───────────────┘ └─┘ ┴ └┘ ┴ └───────────────┘ ┴
typ └───────────────┘ ┴ └┘ └─┘ └┘ ┴ ┴ └┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ └┘ ┴ ┴
810 by induction ys generalizing f; simp *
id └┘
src └────────┘ └─────────────┘ └──────
typ └────────┘└┘└─────────────┘ └──────
doc └────────┘ └─────────────┘ └──────
txt └────────┘ └─────────────┘ └──────
par └────────┘ └─────────────┘ └──────
pid ┴ ┴└────────────┘ ┴┴└
st └────────────────────────────────────
811
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
812 theorem mem_permutations_aux2 {t : α} {ts : list α} {ys : list α} {l l' : list α} :
id ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴
src └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴
813 l' ∈ (permutations_aux2 t ts [] ys (append l)).2 ↔
id └┘ ┴ └───────────────┘ ┴ └┘ └┘ └┘ └────┘ ┴ ┴ ┴
src ┴ └───────────────┘ └┘ └────┘ ┴ ┴
typ └┘ ┴ └───────────────┘ ┴ └┘ └┘ └┘ └────┘ ┴ ┴ ┴
814 ∃ l₁ l₂, l₂ ≠ [] ∧ ys = l₁ ++ l₂ ∧ l' = l ++ l₁ ++ t :: l₂ ++ ts :=
id ┴ └┘ └┘┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘ └┘ └┘ ┴ └┘ ┴ ┴ └┘ └┘ └┘ ┴ └┘ └┘ └┘ └┘
src ┴ ┴ ┴ └┘ ┴ ┴ └┘ ┴ ┴ └┘ └┘ └┘ └┘
typ ┴ └┘ └┘┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘ └┘ └┘ ┴ └┘ ┴ ┴ └┘ └┘ └┘ ┴ └┘ └┘ └┘ └┘
815 begin
st └─────
816 induction ys with y ys ih generalizing l,
id └┘
src └────────┘ └──────────────────────────┘
typ └────────┘└┘└──────────────────────────┘
doc └────────┘ └──────────────────────────┘
txt └────────┘ └──────────────────────────┘
par └────────┘ └──────────────────────────┘
pid ┴ ┴└──────────┘└─────────────┘
st ─────────────────────────────────────────┘└─
817 { simp {contextual := tt} },
id └┘
src └───┘ └────────────┘└┘└┘
typ └───┘ └────────────┘└┘└┘
doc └───┘ └────────────┘ └┘
txt └───┘ └────────────┘ └┘
par └───┘ └────────────┘ └┘
pid ┴ └────────────┘ ┴┴
st ───┘└──────────────────────┘└┘└
818 { rw [permutations_aux2_snd_cons, show (λ (x : list α), l ++ y :: x) = append (l ++ [y]),
id └────────────────────────┘ └──┘ ┴ ┴ └────┘ ┴ ┴┴┴
src └──┘└────────────────────────┘└┘ ┴ └────┘└──┘┴ └─┘ ┴ ┴ ┴ ┴ └┘┴┴└────┘┴ ┴ ┴┴ ┴└──
typ └──┘└────────────────────────┘└┘ ┴ └────┘└──┘┴┴└─┘ ┴ ┴ ┴ ┴ └┘┴┴└────┘┴ ┴┴ ┴┴┴┴└──
doc └──┘ └┘ ┴ └────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └──
txt └──┘ └┘ ┴ └────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └──
par └──┘ └┘ ┴ └────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └──
pid └┘ └┘ ┴ └────┘ ┴ └─┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └──
st ─────────────────────────────────┘└─────────────────────────────────────────────────────────
819 by funext; simp, mem_cons_iff, ih], split; intro h,
id └──────────┘
src ──────────┘└────┘└┘└──┘└┘└──────────┘└┘ ┴ └───┘ └─────┘
typ ──────────┘└────┘└┘└──┘└┘└──────────┘└┘└┘┴ └───┘ └─────┘
doc ──────────┘└────┘└┘└──┘└┘ └┘ ┴ └───┘ └─────┘
txt ──────────┘└────┘└┘└──┘└┘ └┘ ┴ └───┘ └─────┘
par ──────────┘└────┘└┘└──┘└┘ └┘ ┴ └───┘ └─────┘
pid ────────────────────────┘ └┘ ┴ └┘
st ─────────┘└───────────┘└────────────┘└──┘┴└──────────────┘└─
820 { rcases h with e | ⟨l₁, l₂, l0, ye, _⟩,
id ┴
src └─────┘ └───────────────────────────┘
typ └─────┘┴└───────────────────────────┘
doc └─────┘ └───────────────────────────┘
txt └─────┘ └───────────────────────────┘
par └─────┘ └───────────────────────────┘
pid ┴ └───────────────────────────┘
st ─────┘└───────────────────────────────────┘└─
821 { subst l', exact ⟨[], y::ys, by simp⟩ },
id └┘ ┴ └┘
src └────┘ └────┘ └┘ └┘ ┴└──┘└┘
typ └────┘└┘ └────┘ └┘┴ └┘└┘ ┴└──┘└┘
doc └────┘ └────┘ └┘ └┘ ┴└──┘└┘
txt └────┘ └────┘ └┘ └┘ ┴└──┘└┘
par └────┘ └────┘ └┘ └┘ ┴└──┘└┘
pid ┴ ┴ └┘ └┘ └────┘┴
st ───────┘└──────┘└────────────────────┘└───┘└┘└┘└
822 { substs l' ys, exact ⟨y::l₁, l₂, l0, by simp⟩ } },
id ┴ └┘ └┘ └┘
src └──────────┘ └────┘ └┘ └┘ └┘ ┴└──┘└┘
typ └──────────┘ └────┘ ┴ └┘└┘└┘└┘└┘└┘ ┴└──┘└┘
doc └──────────┘ └────┘ └┘ └┘ └┘ ┴└──┘└┘
txt └──────────┘ └────┘ └┘ └┘ └┘ ┴└──┘└┘
par └──────────┘ └────┘ └┘ └┘ └┘ ┴└──┘└┘
pid └────┘ ┴ └┘ └┘ └┘ └────┘┴
st ───────────────────┘└────────────────────────┘└───┘└┘└──┘└
823 { rcases h with ⟨_ | ⟨y', l₁⟩, l₂, l0, ye, rfl⟩,
id ┴
src └─────┘ └───────────────────────────────────┘
typ └─────┘┴└───────────────────────────────────┘
doc └─────┘ └───────────────────────────────────┘
txt └─────┘ └───────────────────────────────────┘
par └─────┘ └───────────────────────────────────┘
pid ┴ └───────────────────────────────────┘
st ──────────────────────────────────────────────────┘└─
824 { simp [ye] },
id └┘
src └────┘ └┘
typ └────┘└┘└┘
doc └────┘ └┘
txt └────┘ └┘
par └────┘ └┘
pid ┴┴ ┴┴
st ───────┘└────────┘└┘└
825 { simp at ye, rcases ye with ⟨rfl, rfl⟩,
id └┘
src └────────┘ └─────┘ └──────────────┘
typ └────────┘ └─────┘└┘└──────────────┘
doc └────────┘ └─────┘ └──────────────┘
txt └────────┘ └─────┘ └──────────────┘
par └────────┘ └─────┘ └──────────────┘
pid ┴└───┘ ┴ └──────────────┘
st ─────────────────┘└─────────────────────────┘└─
826 exact or.inr ⟨l₁, l₂, l0, by simp⟩ } } }
id └────┘ └┘ └┘ └┘
src └────┘└────┘┴ └┘ └┘ └┘ ┴└──┘└┘
typ └────┘└────┘┴ └┘└┘└┘└┘└┘└┘ ┴└──┘└┘
doc └────┘ ┴ └┘ └┘ └┘ ┴└──┘└┘
txt └────┘ ┴ └┘ └┘ └┘ ┴└──┘└┘
par └────┘ ┴ └┘ └┘ └┘ ┴└──┘└┘
pid ┴ ┴ └┘ └┘ └┘ └────┘┴
st ───────────────────────────────────┘└───┘└┘└─────
827 end
st ──┘
828
829 theorem mem_permutations_aux2' {t : α} {ts : list α} {ys : list α} {l : list α} :
id ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴
src └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴
830 l ∈ (permutations_aux2 t ts [] ys id).2 ↔
id ┴ ┴ └───────────────┘ ┴ └┘ └┘ └┘ └┘ ┴ ┴
src ┴ └───────────────┘ └┘ └┘ ┴ ┴
typ ┴ ┴ └───────────────┘ ┴ └┘ └┘ └┘ └┘ ┴ ┴
831 ∃ l₁ l₂, l₂ ≠ [] ∧ ys = l₁ ++ l₂ ∧ l = l₁ ++ t :: l₂ ++ ts :=
id ┴ └┘ └┘┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘ └┘ └┘ ┴ ┴ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘
src ┴ ┴ ┴ └┘ ┴ ┴ └┘ ┴ ┴ └┘ └┘ └┘
typ ┴ └┘ └┘┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘ └┘ └┘ ┴ ┴ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘
832 by rw [show @id (list α) = append nil, by funext; refl]; apply mem_permutations_aux2
id └┘ └──┘ ┴ ┴ └────┘ └─┘ └───────────────────┘
src └──┘ ┴ └┘┴ └──┘┴ └┘┴┴└────┘┴└─┘└───┘└────┘└┘└──┘┴ └────┘└───────────────────┘└
typ └──┘ ┴ └┘┴ └──┘┴┴└┘┴┴└────┘┴└─┘└───┘└────┘└┘└──┘┴ └────┘└───────────────────┘└
doc └──┘ ┴ ┴ ┴ └┘ ┴ ┴ └───┘└────┘└┘└──┘┴ └────┘ └
txt └──┘ ┴ ┴ ┴ └┘ ┴ ┴ └───┘└────┘└┘└──┘┴ └────┘ └
par └──┘ ┴ ┴ ┴ └┘ ┴ ┴ └───┘└────┘└┘└──┘┴ └────┘ └
pid └┘ ┴ ┴ ┴ └┘ ┴ ┴ └────────────────┘ ┴ └
st └─────────────────────────────────────┘└───────────┘┴└─────────────────────────────
833
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
834 theorem length_permutations_aux2 (t : α) (ts : list α) (ys : list α) (f : list α → β) :
id ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ ┴
src └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ ┴ └──┘ ┴ ┴
835 length (permutations_aux2 t ts [] ys f).2 = length ys :=
id └────┘ └───────────────┘ ┴ └┘ └┘ └┘ ┴ ┴ ┴ └────┘ └┘
src └────┘ └───────────────┘ └┘ ┴ ┴ └────┘
typ └────┘ └───────────────┘ ┴ └┘ └┘ └┘ ┴ ┴ ┴ └────┘ └┘
836 by induction ys generalizing f; simp *
id └┘
src └────────┘ └─────────────┘ └──────
typ └────────┘└┘└─────────────┘ └──────
doc └────────┘ └─────────────┘ └──────
txt └────────┘ └─────────────┘ └──────
par └────────┘ └─────────────┘ └──────
pid ┴ ┴└────────────┘ ┴┴└
st └────────────────────────────────────
837
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
838 theorem foldr_permutations_aux2 (t : α) (ts : list α) (r L : list (list α)) :
id ┴ └──┘ ┴ └──┘ └──┘ ┴
src └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ └──┘ ┴
839 foldr (λy r, (permutations_aux2 t ts r y id).2) r L = L.bind (λ y, (permutations_aux2 t ts [] y id).2) ++ r :=
id └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴└───┘ ┴ └───────────────┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴
src └───┘ └───────────────┘ └┘ ┴ ┴ └───┘ └───────────────┘ └┘ └┘ ┴ └┘
typ └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴└───┘ ┴ └───────────────┘ ┴ └┘ └┘ ┴ └┘ ┴ └┘ ┴
840 by induction L with l L ih; [refl, {simp [ih], rw ← permutations_aux2_append}]
id ┴ ┴ └┘ └──────────────────────┘
src └────────┘ └──────────┘ ┴└──┘ └────┘ ┴ └───┘└──────────────────────┘
typ └────────┘┴└──────────┘ ┴└──┘ └────┘└┘┴ └───┘└──────────────────────┘
doc └────────┘ └──────────┘ └──┘ └────┘ ┴ └───┘
txt └────────┘ └──────────┘ └──┘ └────┘ ┴ └───┘
par └────────┘ └──────────┘ └──┘ └────┘ ┴ └───┘
pid ┴ ┴└─────────┘ ┴┴ ┴ └─┘
st └───────────────────────────────┘└────────┘└─────────────────────────────┘└┘
841
842 theorem mem_foldr_permutations_aux2 {t : α} {ts : list α} {r L : list (list α)} {l' : list α} :
id ┴ └──┘ ┴ └──┘ └──┘ ┴ └──┘ ┴
src └──┘ └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ └──┘ ┴ └──┘ ┴
843 l' ∈ foldr (λy r, (permutations_aux2 t ts r y id).2) r L ↔ l' ∈ r ∨
id └┘ ┴ └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
src ┴ └───┘ └───────────────┘ └┘ ┴ ┴ ┴ ┴
typ └┘ ┴ └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘ ┴ ┴ ┴
844 ∃ l₁ l₂, l₁ ++ l₂ ∈ L ∧ l₂ ≠ [] ∧ l' = l₁ ++ t :: l₂ ++ ts :=
id ┴ └┘ └┘┴ └┘ └┘ └┘ ┴ ┴ ┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘
src ┴ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ └┘ └┘ └┘
typ ┴ └┘ └┘┴ └┘ └┘ └┘ ┴ ┴ ┴ └┘ ┴ └┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘
845 have (∃ (a : list α), a ∈ L ∧
id ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴
src ┴ └──┘ ┴ ┴ ┴
typ ┴ └──┘ ┴ ┴ ┴ ┴ ┴ ┴
846 ∃ (l₁ l₂ : list α), ¬l₂ = nil ∧ a = l₁ ++ l₂ ∧ l' = l₁ ++ t :: (l₂ ++ ts)) ↔
id ┴ └──┘ ┴ ┴ ┴└┘ ┴ └─┘ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘ ┴
src ┴ └──┘ ┴ ┴ ┴ └─┘ ┴ ┴ └┘ ┴ ┴ └┘ └┘ └┘ ┴
typ ┴ └──┘ ┴ ┴ ┴└┘ ┴ └─┘ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘ ┴
847 ∃ (l₁ l₂ : list α), ¬l₂ = nil ∧ l₁ ++ l₂ ∈ L ∧ l' = l₁ ++ t :: (l₂ ++ ts),
id ┴ └──┘ ┴ ┴ ┴└┘ ┴ └─┘ ┴ └┘ └┘ └┘ ┴ ┴ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘
src ┴ └──┘ ┴ ┴ ┴ └─┘ ┴ └┘ ┴ ┴ ┴ └┘ └┘ └┘
typ ┴ └──┘ ┴ ┴ ┴└┘ ┴ └─┘ ┴ └┘ └┘ └┘ ┴ ┴ ┴ └┘ ┴ └┘ └┘ ┴ └┘ └┘ └┘ └┘
848 from ⟨λ ⟨a, aL, l₁, l₂, l0, e, h⟩, ⟨l₁, l₂, l0, e ▸ aL, h⟩,
id ┴ └┘ └┘ └┘ └┘ ┴ ┴ ┴
src ┴
typ ┴ └┘ └┘ └┘ └┘ ┴ ┴ ┴
849 λ ⟨l₁, l₂, l0, aL, h⟩, ⟨_, aL, l₁, l₂, l0, rfl, h⟩⟩,
id ┴└┘ └┘ └┘ └┘ ┴ └─┘
src └─┘
typ ┴└┘ └┘ └┘ └┘ ┴ └─┘
850 by rw foldr_permutations_aux2; simp [mem_permutations_aux2', this,
id └─────────────────────┘ └────────────────────┘ └──┘
src └─┘└─────────────────────┘ └────┘└────────────────────┘└┘ └─
typ └─┘└─────────────────────┘ └────┘└────────────────────┘└┘└──┘└─
doc └─┘ └────┘ └┘ └─
txt └─┘ └────┘ └┘ └─
par └─┘ └────┘ └┘ └─
pid ┴ ┴┴ └┘ └─
st └────────────────────────────────────────────────────────────────
851 or.comm, or.left_comm, or.assoc, and.comm, and.left_comm, and.assoc]
id └─────┘ └──────────┘ └──────┘ └──────┘ └───────────┘ └───────┘
src ─┘└─────┘└┘└──────────┘└┘└──────┘└┘└──────┘└┘└───────────┘└┘└───────┘└─
typ ─┘└─────┘└┘└──────────┘└┘└──────┘└┘└──────┘└┘└───────────┘└┘└───────┘└─
doc ─┘ └┘ └┘ └┘ └┘ └┘ └─
txt ─┘ └┘ └┘ └┘ └┘ └┘ └─
par ─┘ └┘ └┘ └┘ └┘ └┘ └─
pid ─┘ └┘ └┘ └┘ └┘ └┘ ┴└
st ───────────────────────────────────────────────────────────────────────
852
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
853 theorem length_foldr_permutations_aux2 (t : α) (ts : list α) (r L : list (list α)) :
id ┴ └──┘ ┴ └──┘ └──┘ ┴
src └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ └──┘ ┴
854 length (foldr (λy r, (permutations_aux2 t ts r y id).2) r L) = sum (map length L) + length r :=
id └────┘ └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └─┘ └─┘ └────┘ ┴ ┴ └────┘ ┴
src └────┘ └───┘ └───────────────┘ └┘ ┴ ┴ └─┘ └─┘ └────┘ ┴ └────┘
typ └────┘ └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └─┘ └─┘ └────┘ ┴ ┴ └────┘ ┴
doc └─┘
855 by simp [foldr_permutations_aux2, (∘), length_permutations_aux2]
id └─────────────────────┘ ┴ └──────────────────────┘
src └────┘└─────────────────────┘└┘┴└──┘└──────────────────────┘└─
typ └────┘└─────────────────────┘└┘┴└──┘└──────────────────────┘└─
doc └────┘ └┘ └──┘ └─
txt └────┘ └┘ └──┘ └─
par └────┘ └┘ └──┘ └─
pid ┴┴ └┘ └──┘ ┴└
st └──────────────────────────────────────────────────────────────
856
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
857 theorem length_foldr_permutations_aux2' (t : α) (ts : list α) (r L : list (list α))
id ┴ └──┘ ┴ └──┘ └──┘ ┴
src └──┘ └──┘ └──┘
typ ┴ └──┘ ┴ └──┘ └──┘ ┴
858 (n) (H : ∀ l ∈ L, length l = n) :
id ┴ ┴ └────┘ ┴ ┴ ┴
src └────┘ ┴
typ ┴ ┴ └────┘ ┴ ┴ ┴
859 length (foldr (λy r, (permutations_aux2 t ts r y id).2) r L) = n * length L + length r :=
id └────┘ └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └────┘ ┴
src └────┘ └───┘ └───────────────┘ └┘ ┴ ┴ ┴ └────┘ ┴ └────┘
typ └────┘ └───┘ ┴ ┴ └───────────────┘ ┴ └┘ ┴ ┴ └┘ ┴ ┴ ┴ ┴ ┴ ┴ └────┘ ┴ ┴ └────┘ ┴
860 begin
st └─────
861 rw [length_foldr_permutations_aux2, (_ : sum (map length L) = n * length L)],
id └────────────────────────────┘ └─┘ └─┘ ┴ ┴ ┴ └────┘ ┴
src └──┘└────────────────────────────┘└┘ └──┘└─┘┴ └─┘┴ ┴ └┘┴┴ ┴┴┴└────┘┴ └┘
typ └──┘└────────────────────────────┘└┘ └──┘└─┘┴ └─┘┴ ┴ └┘┴┴┴┴┴┴└────┘┴┴└┘
doc └──┘ └┘ └──┘└─┘┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘
txt └──┘ └┘ └──┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘
par └──┘ └┘ └──┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘
pid └┘ └┘ └──┘ ┴ ┴ ┴ └┘ ┴ ┴ ┴ ┴ └┘
st ───────────────────────────────────┘└───────────────────────────────────────┘└──
862 induction L with l L ih, {simp},
id ┴
src └────────┘ └──────────┘ └──┘
typ └────────┘┴└──────────┘ └──┘
doc └────────┘ └──────────┘ └──┘
txt └────────┘ └──────────┘ └──┘
par └────────┘ └──────────┘ └──┘
pid ┴ ┴└─────────┘
st ────────────────────────┘└─────┘└┘└
863 simp [ih (λ l m, H l (mem_cons_of_mem _ m)), H l (mem_cons_self _ _), mul_add]
id └┘ ┴ └─────────────┘ ┴ ┴ └───────────┘ └─────┘
src └────┘ ┴ └────┘ ┴ ┴ └─────────────┘└─┘ └──┘ ┴ ┴ └───────────┘└─────┘└─────┘└┘
typ └────┘└┘┴ └────┘┴┴ ┴ └─────────────┘└─┘ └──┘┴┴┴┴ └───────────┘└─────┘└─────┘└┘
doc └────┘ ┴ └────┘ ┴ ┴ └─┘ └──┘ ┴ ┴ └─────┘ └┘
txt └────┘ ┴ └────┘ ┴ ┴ └─┘ └──┘ ┴ ┴ └─────┘ └┘
par └────┘ ┴ └────┘ ┴ ┴ └─┘ └──┘ ┴ ┴ └─────┘ └┘
pid ┴┴ ┴ └────┘ ┴ ┴ └─┘ └──┘ ┴ ┴ └─────┘ ┴┴
st ────────────────────────────────────────────────────────────────────────────────┘
864 end
st └─┘
865
866 theorem perm_of_mem_permutations_aux :
867 ∀ {ts is l : list α}, l ∈ permutations_aux ts is → l ~ ts ++ is :=
id └──┘ ┴ ┴ ┴ └──────────────┘ └┘ └┘ ┴ ┴ └┘ └┘ └┘
src └──┘ ┴ └──────────────┘ ┴ └┘
typ └──┘ ┴ ┴ ┴ └──────────────┘ └┘ └┘ ┴ ┴ └┘ └┘ └┘
doc ┴
868 begin
st └─────
869 refine permutations_aux.rec (by simp) _,
id └──────────────────┘
src └─────┘└──────────────────┘┴ ┴└──┘└─┘
typ └─────┘└──────────────────┘┴ ┴└──┘└─┘
doc └─────┘ ┴ ┴└──┘└─┘
txt └─────┘ ┴ ┴└──┘└─┘
par └─────┘ ┴ ┴└──┘└─┘
pid ┴ ┴ └──────┘
st ────────────────────────────────┘└───┘└─┘└─
870 introv IH1 IH2 m,
src └──────────────┘
typ └──────────────┘
doc └──────────────┘
txt └──────────────┘
par └──────────────┘
pid └────────┘
st ─────────────────┘└─
871 rw [permutations_aux_cons, permutations, mem_foldr_permutations_aux2] at m,
id └───────────────────┘ └──────────┘ └─────────────────────────┘
src └──┘└───────────────────┘└┘└──────────┘└┘└─────────────────────────┘└────┘
typ └──┘└───────────────────┘└┘└──────────┘└┘└─────────────────────────┘└────┘
doc └──┘ └┘└──────────┘└┘ └────┘
txt └──┘ └┘ └┘ └────┘
par └──┘ └┘ └┘ └────┘
pid └┘ └┘ └┘ ┴└───┘
st ──────────────────────────┘└────────────┘└───────────────────────────┘┴└───┘└─
872 rcases m with m | ⟨l₁, l₂, m, _, e⟩,
id ┴
src └─────┘ └─────────────────────────┘
typ └─────┘┴└─────────────────────────┘
doc └─────┘ └─────────────────────────┘
txt └─────┘ └─────────────────────────┘
par └─────┘ └─────────────────────────┘
pid ┴ └─────────────────────────┘
st ────────────────────────────────────┘└─
873 { exact (IH1 m).trans perm_middle },
id └─┘ ┴ └─────────┘
src └────┘ ┴ └──────┘└─────────┘┴
typ └────┘ └─┘┴┴└──────┘└─────────┘┴
doc └────┘ ┴ └──────┘ ┴
txt └────┘ ┴ └──────┘ ┴
par └────┘ ┴ └──────┘ ┴
pid ┴ ┴ └──────┘ ┴
st ───┘└──────────────────────────────┘└┘└
874 { subst e,
id ┴
src └────┘
typ └────┘┴
doc └────┘
txt └────┘
par └────┘
pid ┴
st ──────────┘└─
875 have p : l₁ ++ l₂ ~ is,
id └┘ └┘ └┘ ┴ └┘
src └───────┘ ┴└┘┴ ┴┴┴
typ └───────┘└┘┴└┘┴└┘┴┴┴└┘
doc └───────┘ ┴ ┴ ┴┴┴
txt └───────┘ ┴ ┴ ┴ ┴
par └───────┘ ┴ ┴ ┴ ┴
pid └────┘└─┘ ┴ ┴ ┴ ┴
st ─────────────────────────┘└─
876 { simp [permutations] at m,
id └──────────┘
src └────┘└──────────┘└────┘
typ └────┘└──────────┘└────┘
doc └────┘└──────────┘└────┘
txt └────┘ └────┘
par └────┘ └────┘
pid ┴┴ ┴┴└──┘
st ─────┘└──────────────────────┘└─
877 cases m with e m, {simp [e]},
id ┴ ┴
src └────┘ └───────┘ └────┘ ┴
typ └────┘┴└───────┘ └────┘┴┴
doc └────┘ └───────┘ └────┘ ┴
txt └────┘ └───────┘ └────┘ ┴
par └────┘ └───────┘ └────┘ ┴
pid ┴ └───────┘ ┴┴ ┴
st ─────────────────────┘└─────────┘└┘└
878 exact is.append_nil ▸ IH2 m },
id └───────────┘ ┴ └─┘ ┴
src └────┘└───────────┘┴┴┴ ┴ ┴
typ └────┘└───────────┘┴┴┴└─┘┴┴┴
doc └────┘ ┴ ┴ ┴ ┴
txt └────┘ ┴ ┴ ┴ ┴
par └────┘ ┴ ┴ ┴ ┴
pid ┴ ┴ ┴ ┴ ┴
st ─────────────────────────────────┘└┘└
879 exact (perm_app_left _ (perm_middle.trans (skip _ p))).trans (skip _ perm_app_comm) }
id └───────────┘ └───────────────┘ ┴ └──┘ └───────────┘
src └────┘ └───────────┘└─┘ └───────────────┘┴ └─┘ └────────┘ └──┘└─┘└───────────┘└┘
typ └────┘ └───────────┘└─┘ └───────────────┘┴ └─┘┴└────────┘ └──┘└─┘└───────────┘└┘
doc └────┘ └─┘ ┴ └─┘ └────────┘ └─┘ └┘
txt └────┘ └─┘ ┴ └─┘ └────────┘ └─┘ └┘
par └────┘ └─┘ ┴ └─┘ └────────┘ └─┘ └┘
pid ┴ └─┘ ┴ └─┘ └────────┘ └─┘ ┴┴
st ───────────────────────────────────────────────────────────────────────────────────────┘└─
880 end
st ──┘
881
882 theorem perm_of_mem_permutations {l₁ l₂ : list α}
id └──┘ ┴
src └──┘
typ └──┘ ┴
883 (h : l₁ ∈ permutations l₂) : l₁ ~ l₂ :=
id └┘ ┴ └──────────┘ └┘ └┘ ┴ └┘
src ┴ └──────────┘ ┴
typ └┘ ┴ └──────────┘ └┘ └┘ ┴ └┘
doc └──────────┘ ┴
884 (eq_or_mem_of_mem_cons h).elim (λ e, e ▸ perm.refl _)
id └───────────────────┘ ┴ └──┘ ┴ ┴ ┴ └───────┘
src └───────────────────┘ └──┘ ┴ └───────┘
typ └───────────────────┘ ┴ └──┘ ┴ ┴ ┴ └───────┘
885 (λ m, append_nil l₂ ▸ perm_of_mem_permutations_aux m)
id ┴ └────────┘ └┘ ┴ └──────────────────────────┘ ┴
src └────────┘ ┴ └──────────────────────────┘
typ ┴ └────────┘ └┘ ┴ └──────────────────────────┘ ┴
886
887 theorem length_permutations_aux :
888 ∀ ts is : list α, length (permutations_aux ts is) + is.length.fact = (length ts + length is).fact :=
id └──┘ ┴ └────┘ └──────────────┘ └┘ └┘ ┴ └┘└─────┘└───┘ ┴ └────┘ └┘ ┴ └────┘ └┘ └──┘
src └──┘ └────┘ └──────────────┘ ┴ └─────┘└───┘ ┴ └────┘ ┴ └────┘ └──┘
typ └──┘ ┴ └────┘ └──────────────┘ └┘ └┘ ┴ └┘└─────┘└───┘ ┴ └────┘ └┘ ┴ └────┘ └┘ └──┘
doc └───┘ └──┘
889 begin
st └─────
890 refine permutations_aux.rec (by simp) _,
id └──────────────────┘
src └─────┘└──────────────────┘┴ ┴└──┘└─┘
typ └─────┘└──────────────────┘┴ ┴└──┘└─┘
doc └─────┘ ┴ ┴└──┘└─┘
txt └─────┘ ┴ ┴└──┘└─┘
par └─────┘ ┴ ┴└──┘└─┘
pid ┴ ┴ └──────┘
st ────────────────────────────────┘└───┘└─┘└─
891 intros t ts is IH1 IH2,
src └────────────────────┘
typ └────────────────────┘
doc └────────────────────┘
txt └────────────────────┘
par └────────────────────┘
pid └──────────────┘
st ───────────────────────┘└─
892 have IH2 : length (permutations_aux is nil) + 1 = is.length.fact,
id └────┘ └──────────────┘ └─┘ ┴ ┴ └────────────┘
src └─────────┘└────┘┴ └──────────────┘┴ ┴└─┘└┘┴└─┘┴┴└────────────┘
typ └─────────┘└────┘┴ └──────────────┘┴ ┴└─┘└┘┴└─┘┴┴└────────────┘
doc └─────────┘ ┴ ┴ ┴ └┘ └─┘ ┴└────────────┘
txt └─────────┘ ┴ ┴ ┴ └┘ └─┘ ┴
par └─────────┘ ┴ ┴ ┴ └┘ └─┘ ┴
pid └──────┘└─┘ ┴ ┴ ┴ └┘ └─┘ ┴
st ─────────────────────────────────────────────────────────────────┘└─
893 { simpa using IH2 },
id └─┘
src └──────────┘ ┴
typ └──────────┘└─┘┴
doc └──────────┘ ┴
txt └──────────┘ ┴
par └──────────┘ ┴
pid ┴└────┘ ┴
st ───┘└──────────────┘└┘└
894 simp [-add_comm, nat.fact, nat.add_succ, mul_comm] at IH1,
id └──────┘ └──────────┘ └──────┘
src └───────────────┘└──────┘└┘└──────────┘└┘└──────┘└──────┘
typ └───────────────┘└──────┘└┘└──────────┘└┘└──────┘└──────┘
doc └───────────────┘└──────┘└┘ └┘ └──────┘
txt └───────────────┘ └┘ └┘ └──────┘
par └───────────────┘ └┘ └┘ └──────┘
pid ┴└──────────┘ └┘ └┘ ┴┴└────┘
st ──────────────────────────────────────────────────────────┘└─
895 rw [permutations_aux_cons,
id └───────────────────┘
src └──┘└───────────────────┘└─
typ └──┘└───────────────────┘└─
doc └──┘ └─
txt └──┘ └─
par └──┘ └─
pid └┘ └─
st ──────────────────────────┘└─
896 length_foldr_permutations_aux2' _ _ _ _ _
id └─────────────────────────────┘
src ─────┘└─────────────────────────────┘└──────────
typ ─────┘└─────────────────────────────┘└──────────
doc ─────┘ └──────────
txt ─────┘ └──────────
par ─────┘ └──────────
pid ─────┘ └──────────
st ────────────────────────────────────────────────
897 (λ l m, perm_length (perm_of_mem_permutations m)),
id └─────────┘ └──────────────────────┘
src ───────┘ └────┘└─────────┘┴ └──────────────────────┘┴ └───
typ ───────┘ └────┘└─────────┘┴ └──────────────────────┘┴ └───
doc ───────┘ └────┘ ┴ ┴ └───
txt ───────┘ └────┘ ┴ ┴ └───
par ───────┘ └────┘ ┴ ┴ └───
pid ───────┘ └────┘ ┴ ┴ └───
st ────────────────────────────────────────────────────────┘└─
898 permutations, length, length, IH2,
id └──────────┘ └────┘ └────┘ └─┘
src ─────┘└──────────┘└┘└────┘└┘└────┘└┘ └─
typ ─────┘└──────────┘└┘└────┘└┘└────┘└┘└─┘└─
doc ─────┘└──────────┘└┘ └┘ └┘ └─
txt ─────┘ └┘ └┘ └┘ └─
par ─────┘ └┘ └┘ └┘ └─
pid ─────┘ └┘ └┘ └┘ └─
st ─────────────────┘└──────┘└──────┘└───┘└─
899 nat.succ_add, nat.fact_succ, mul_comm (nat.succ _), ← IH1,
id └──────────┘ └───────────┘ └──────┘ └──────┘ └─┘
src ─────┘└──────────┘└┘└───────────┘└┘└──────┘┴ └──────┘└─────┘ └─
typ ─────┘└──────────┘└┘└───────────┘└┘└──────┘┴ └──────┘└─────┘└─┘└─
doc ─────┘ └┘ └┘ ┴ └─────┘ └─
txt ─────┘ └┘ └┘ ┴ └─────┘ └─
par ─────┘ └┘ └┘ ┴ └─────┘ └─
pid ─────┘ └┘ └┘ ┴ └─────┘ └─
st ─────────────────┘└─────────────┘└─────────────────────┘└─────┘└─
900 add_comm (_*_), add_assoc, nat.mul_succ, mul_comm]
id └──────┘ ┴ └───────┘ └──────────┘ └──────┘
src ─────┘└──────┘┴ ┴┴└──┘└───────┘└┘└──────────┘└┘└──────┘└┘
typ ─────┘└──────┘┴ ┴┴└──┘└───────┘└┘└──────────┘└┘└──────┘└┘
doc ─────┘ ┴ ┴ └──┘ └┘ └┘ └┘
txt ─────┘ ┴ ┴ └──┘ └┘ └┘ └┘
par ─────┘ ┴ ┴ └──┘ └┘ └┘ └┘
pid ─────┘ ┴ ┴ └──┘ └┘ └┘ ┴┴
st ───────────────────┘└─────────┘└────────────┘└────────┘┴┴
901 end
st └─┘
902
903 theorem length_permutations (l : list α) : length (permutations l) = (length l).fact :=
id └──┘ ┴ └────┘ └──────────┘ ┴ ┴ └────┘ ┴ └──┘
src └──┘ └────┘ └──────────┘ ┴ └────┘ └──┘
typ └──┘ ┴ └────┘ └──────────┘ ┴ ┴ └────┘ ┴ └──┘
doc └──────────┘ └──┘
904 length_permutations_aux l []
id └─────────────────────┘ ┴ └┘
src └─────────────────────┘ └┘
typ └─────────────────────┘ ┴ └┘
905
906 theorem mem_permutations_of_perm_lemma {is l : list α}
id └──┘ ┴
src └──┘
typ └──┘ ┴
907 (H : l ~ [] ++ is → (∃ ts' ~ [], l = ts' ++ is) ∨ l ∈ permutations_aux is [])
id ┴ ┴ └┘ └┘ └┘ ┴ └─┘ └┘┴ ┴ ┴ └─┘ └┘ └┘ ┴ ┴ ┴ └──────────────┘ └┘ └┘
src ┴ └┘ └┘ ┴ └┘┴ ┴ └┘ ┴ ┴ └──────────────┘ └┘
typ ┴ ┴ └┘ └┘ └┘ ┴ └─┘ └┘┴ ┴ ┴ └─┘ └┘ └┘ ┴ ┴ ┴ └──────────────┘ └┘ └┘
doc ┴
908 : l ~ is → l ∈ permutations is :=
id ┴ ┴ └┘ ┴ ┴ └──────────┘ └┘
src ┴ ┴ └──────────┘
typ ┴ ┴ └┘ ┴ ┴ └──────────┘ └┘
doc ┴ └──────────┘
909 by simpa [permutations, perm_nil] using H
id └──────────┘ └──────┘ ┴
src └─────┘└──────────┘└┘└──────┘└──────┘ └
typ └─────┘└──────────┘└┘└──────┘└──────┘┴└
doc └─────┘└──────────┘└┘ └──────┘ └
txt └─────┘ └┘ └──────┘ └
par └─────┘ └┘ └──────┘ └
pid ┴┴ └┘ ┴┴└────┘ └
st └───────────────────────────────────────
910
src ┘
typ ┘
doc ┘
txt ┘
par ┘
pid ┘
st ┘
911 theorem mem_permutations_aux_of_perm :
912 ∀ {ts is l : list α}, l ~ is ++ ts → (∃ is' ~ is, l = is' ++ ts) ∨ l ∈ permutations_aux ts is :=
id └──┘ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └─┘ └┘┴ ┴ ┴ └─┘ └┘ └┘ ┴ ┴ ┴ └──────────────┘ └┘ └┘
src └──┘ ┴ └┘ ┴ ┴ ┴ └┘ ┴ ┴ └──────────────┘
typ └──┘ ┴ ┴ ┴ └┘ └┘ └┘ ┴ └─┘ └┘┴ ┴ ┴ └─┘ └┘ └┘ ┴ ┴ ┴ └──────────────┘ └┘ └┘
doc ┴
913 begin
st └─────
914 refine permutations_aux.rec (by simp) _,
id └──────────────────┘
src └─────┘└──────────────────┘┴ ┴└──┘└─┘
typ └─────┘└──────────────────┘┴ ┴└──┘└─┘
doc └─────┘ ┴ ┴└──┘└─┘
txt └─────┘ ┴ ┴└──┘└─┘
par └─────┘ ┴ ┴└──┘└─┘
pid ┴ ┴ └──────┘
st ────────────────────────────────┘└───┘└─┘└─
915 intros t ts is IH1 IH2 l p,
src └────────────────────────┘
typ └────────────────────────┘
doc └────────────────────────┘
txt └────────────────────────┘
par └────────────────────────┘
pid └──────────────────┘
st ───────────────────────────┘└─
916 rw [permutations_aux_cons, mem_foldr_permutations_aux2],
id └───────────────────┘ └─────────────────────────┘
src └──┘└───────────────────┘└┘└─────────────────────────┘┴
typ └──┘└───────────────────┘└┘└─────────────────────────┘┴
doc └──┘ └┘ ┴
txt └──┘ └┘ ┴
par └──┘ └┘ ┴
pid └┘ └┘ ┴
st ──────────────────────────┘└───────────────────────────┘└──
917 rcases IH1 (p.trans perm_middle) with ⟨is', p', e⟩ | m,
id └─┘ └─────┘ └─────────┘
src └─────┘ ┴ └─────┘┴└─────────┘└─────────────────────┘
typ └─────┘└─┘┴ └─────┘┴└─────────┘└─────────────────────┘
doc └─────┘ ┴ ┴ └─────────────────────┘
txt └─────┘ ┴ ┴ └─────────────────────┘
par └─────┘ ┴ ┴ └─────────────────────┘
pid ┴ ┴ ┴ └─────────────────────┘
st ───────────────────────────────────────────────────────┘└─
918 { clear p, subst e,
id ┴
src └─────┘ └────┘
typ └─────┘ └────┘┴
doc └─────┘ └────┘
txt └─────┘ └────┘
par └─────┘ └────┘
pid └┘ ┴
st ───┘└─────┘└───────┘└─
919 rcases mem_split (perm_subset p'.symm (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩,
id └───────┘ └─────────┘ └─────┘ └───────────┘
src └─────┘└───────┘┴ └─────────┘┴└─────┘┴ └───────────┘└─────────────────────┘
typ └─────┘└───────┘┴ └─────────┘┴└─────┘┴ └───────────┘└─────────────────────┘
doc └─────┘ ┴ ┴ ┴ └─────────────────────┘
txt └─────┘ ┴ ┴ ┴ └─────────────────────┘
par └─────┘ ┴ ┴ ┴ └─────────────────────┘
pid ┴ ┴ ┴ ┴ └─────────────────────┘
st ──────────────────────────────────────────────────────────────────────────────┘└─
920 subst is',
id └─┘
src └────┘
typ └────┘└─┘
doc └────┘
txt └────┘
par └────┘
pid ┴
st ────────────┘└─
921 have p := perm_cons_inv (perm_middle.symm.trans p'),
id └───────────┘ └────────────────────┘ └┘
src └────────┘└───────────┘┴ └────────────────────┘┴ ┴
typ └────────┘└───────────┘┴ └────────────────────┘┴└┘┴
doc └────────┘ ┴ ┴ ┴
txt └────────┘ ┴ ┴ ┴
par └────────┘ ┴ ┴ ┴
pid └────┘┴└─┘ ┴ ┴ ┴
st ──────────────────────────────────────────────────────┘└─
922 cases l₂ with a l₂',
id └┘
src └────┘ └─────────┘
typ └────┘└┘└─────────┘
doc └────┘ └─────────┘
txt └────┘ └─────────┘
par └────┘ └─────────┘
pid ┴ └─────────┘
st ──────────────────────┘└─
923 { exact or.inl ⟨l₁, by simpa using p⟩ },
id └────┘ └┘ ┴
src └────┘└────┘┴ └┘ ┴└──────────┘ └┘
typ └────┘└────┘┴ └┘└┘ ┴└──────────┘┴└┘
doc └────┘ ┴ └┘ ┴└──────────┘ └┘
txt └────┘ ┴ └┘ ┴└──────────┘ └┘
par └────┘ ┴ └┘ ┴└──────────┘ └┘
pid ┴ ┴ └┘ └───────────┘ ┴┴
st ─────┘└──────────────────┘└────────────┘└┘└┘└
924 { exact or.inr (or.inr ⟨l₁, a::l₂',
id └────┘ └┘ ┴ └─┘
src └────┘ ┴ └────┘┴ └┘ └─
typ └────┘ ┴ └────┘┴ └┘└┘┴ └─┘└─
doc └────┘ ┴ ┴ └┘ └─
txt └────┘ ┴ ┴ └┘ └─
par └────┘ ┴ ┴ └┘ └─
pid ┴ ┴ ┴ └┘ └─
st ────────────────────────────────────────
925 mem_permutations_of_perm_lemma IH2 p, by simp⟩) } },
id └────────────────────────────┘ └─┘ ┴
src ───────┘└────────────────────────────┘┴ ┴ └┘ ┴└──┘└─┘
typ ───────┘└────────────────────────────┘┴└─┘┴┴└┘ ┴└──┘└─┘
doc ───────┘ ┴ ┴ └┘ ┴└──┘└─┘
txt ───────┘ ┴ ┴ └┘ ┴└──┘└─┘
par ───────┘ ┴ ┴ └┘ ┴└──┘└─┘
pid ───────┘ ┴ ┴ └┘ └─────┘┴
st ───────────────────────────────────────────────┘└───┘└─┘└──┘└
926 { exact or.inr (or.inl m) }
id └────┘ └────┘ ┴
src └────┘└────┘┴ └────┘┴ └┘
typ └────┘└────┘┴ └────┘┴┴└┘
doc └────┘ ┴ ┴ └┘
txt └────┘ ┴ ┴ └┘
par └────┘ ┴ ┴ └┘
pid ┴ ┴ ┴ ┴┴
st ───────────────────────────┘└─
927 end
st ──┘
928
929 @[simp] theorem mem_permutations (s t : list α) : s ∈ permutations t ↔ s ~ t :=
id └──┘ ┴ ┴ ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴
src └──┘ ┴ └──────────┘ ┴ ┴
typ └──┘ ┴ ┴ ┴ └──────────┘ ┴ ┴ ┴ ┴ ┴
doc └──┘ └──────────┘ ┴
930 ⟨perm_of_mem_permutations, mem_permutations_of_perm_lemma mem_permutations_aux_of_perm⟩
id └──────────────────────┘ └────────────────────────────┘ └──────────────────────────┘
src └──────────────────────┘ └────────────────────────────┘ └──────────────────────────┘
typ └──────────────────────┘ └────────────────────────────┘ └──────────────────────────┘
931
932 end permutations
933
934 end list